Merge "Use constants for microversion values"
This commit is contained in:
commit
470011b314
@ -24,6 +24,7 @@ from oslo_log import log as logging
|
|||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.common import constants
|
from cinder.common import constants
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
@ -66,8 +67,6 @@ CONF.register_opts(api_common_opts)
|
|||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
_FILTERS_COLLECTION = None
|
_FILTERS_COLLECTION = None
|
||||||
FILTERING_VERSION = '3.31'
|
|
||||||
LIKE_FILTER_VERSION = '3.34'
|
|
||||||
|
|
||||||
ATTRIBUTE_CONVERTERS = {'name~': 'display_name~',
|
ATTRIBUTE_CONVERTERS = {'name~': 'display_name~',
|
||||||
'description~': 'display_description~'}
|
'description~': 'display_description~'}
|
||||||
@ -492,9 +491,9 @@ def process_general_filtering(resource):
|
|||||||
req_version = kwargs.get('req_version')
|
req_version = kwargs.get('req_version')
|
||||||
filters = kwargs.get('filters')
|
filters = kwargs.get('filters')
|
||||||
context = kwargs.get('context')
|
context = kwargs.get('context')
|
||||||
if req_version.matches(FILTERING_VERSION):
|
if req_version.matches(mv.RESOURCE_FILTER):
|
||||||
support_like = False
|
support_like = False
|
||||||
if req_version.matches(LIKE_FILTER_VERSION):
|
if req_version.matches(mv.LIKE_FILTER):
|
||||||
support_like = True
|
support_like = True
|
||||||
reject_invalid_filters(context, filters,
|
reject_invalid_filters(context, filters,
|
||||||
resource, support_like)
|
resource, support_like)
|
||||||
|
@ -20,6 +20,7 @@ from webob import exc
|
|||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder import backup
|
from cinder import backup
|
||||||
from cinder import db
|
from cinder import db
|
||||||
@ -245,7 +246,8 @@ class VolumeAdminController(AdminController):
|
|||||||
volume = self._get(context, id)
|
volume = self._get(context, id)
|
||||||
params = body['os-migrate_volume']
|
params = body['os-migrate_volume']
|
||||||
|
|
||||||
cluster_name, host = common.get_cluster_host(req, params, '3.16')
|
cluster_name, host = common.get_cluster_host(req, params,
|
||||||
|
mv.VOLUME_MIGRATE_CLUSTER)
|
||||||
force_host_copy = utils.get_bool_param('force_host_copy', params)
|
force_host_copy = utils.get_bool_param('force_host_copy', params)
|
||||||
lock_volume = utils.get_bool_param('lock_volume', params)
|
lock_volume = utils.get_bool_param('lock_volume', params)
|
||||||
self.volume_api.migrate_volume(context, volume, host, cluster_name,
|
self.volume_api.migrate_volume(context, volume, host, cluster_name,
|
||||||
|
@ -23,6 +23,7 @@ from webob import exc
|
|||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.views import backups as backup_views
|
from cinder.api.views import backups as backup_views
|
||||||
from cinder import backup as backupAPI
|
from cinder import backup as backupAPI
|
||||||
@ -151,8 +152,8 @@ class BackupsController(wsgi.Controller):
|
|||||||
incremental = backup.get('incremental', False)
|
incremental = backup.get('incremental', False)
|
||||||
force = backup.get('force', False)
|
force = backup.get('force', False)
|
||||||
snapshot_id = backup.get('snapshot_id', None)
|
snapshot_id = backup.get('snapshot_id', None)
|
||||||
metadata = backup.get(
|
metadata = backup.get('metadata', None) if req_version.matches(
|
||||||
'metadata', None) if req_version.matches("3.43") else None
|
mv.BACKUP_METADATA) else None
|
||||||
LOG.info("Creating backup of volume %(volume_id)s in container"
|
LOG.info("Creating backup of volume %(volume_id)s in container"
|
||||||
" %(container)s",
|
" %(container)s",
|
||||||
{'volume_id': volume_id, 'container': container},
|
{'volume_id': volume_id, 'container': container},
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
import oslo_messaging as messaging
|
import oslo_messaging as messaging
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
|
|
||||||
@ -23,7 +24,8 @@ def get_manageable_resources(req, is_detail, function_get_manageable,
|
|||||||
view_builder):
|
view_builder):
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
params = req.params.copy()
|
params = req.params.copy()
|
||||||
cluster_name, host = common.get_cluster_host(req, params, '3.17')
|
cluster_name, host = common.get_cluster_host(
|
||||||
|
req, params, mv.MANAGE_EXISTING_CLUSTER)
|
||||||
marker, limit, offset = common.get_pagination_params(params)
|
marker, limit, offset = common.get_pagination_params(params)
|
||||||
sort_keys, sort_dirs = common.get_sort_params(params,
|
sort_keys, sort_dirs = common.get_sort_params(params,
|
||||||
default_key='reference')
|
default_key='reference')
|
||||||
|
@ -16,14 +16,12 @@
|
|||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.views import scheduler_stats as scheduler_stats_view
|
from cinder.api.views import scheduler_stats as scheduler_stats_view
|
||||||
from cinder.scheduler import rpcapi
|
from cinder.scheduler import rpcapi
|
||||||
from cinder import utils
|
from cinder import utils
|
||||||
|
|
||||||
GET_POOL_NAME_FILTER_MICRO_VERSION = '3.28'
|
|
||||||
GET_POOL_VOLUME_TYPE_FILTER_MICRO_VERSION = '3.35'
|
|
||||||
|
|
||||||
|
|
||||||
def authorize(context, action_name):
|
def authorize(context, action_name):
|
||||||
action = 'scheduler_stats:%s' % action_name
|
action = 'scheduler_stats:%s' % action_name
|
||||||
@ -42,7 +40,7 @@ class SchedulerStatsController(wsgi.Controller):
|
|||||||
@common.process_general_filtering('pool')
|
@common.process_general_filtering('pool')
|
||||||
def _process_pool_filtering(self, context=None, filters=None,
|
def _process_pool_filtering(self, context=None, filters=None,
|
||||||
req_version=None):
|
req_version=None):
|
||||||
if not req_version.matches(GET_POOL_NAME_FILTER_MICRO_VERSION):
|
if not req_version.matches(mv.POOL_FILTER):
|
||||||
filters.clear()
|
filters.clear()
|
||||||
|
|
||||||
def get_pools(self, req):
|
def get_pools(self, req):
|
||||||
@ -60,7 +58,7 @@ class SchedulerStatsController(wsgi.Controller):
|
|||||||
filters=filters,
|
filters=filters,
|
||||||
req_version=req_version)
|
req_version=req_version)
|
||||||
|
|
||||||
if not req_version.matches(GET_POOL_VOLUME_TYPE_FILTER_MICRO_VERSION):
|
if not req_version.matches(mv.POOL_TYPE_FILTER):
|
||||||
filters.pop('volume_type', None)
|
filters.pop('volume_type', None)
|
||||||
|
|
||||||
pools = self.scheduler_api.get_pools(context, filters=filters)
|
pools = self.scheduler_api.get_pools(context, filters=filters)
|
||||||
|
@ -22,6 +22,7 @@ import webob.exc
|
|||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.backup import rpcapi as backup_rpcapi
|
from cinder.backup import rpcapi as backup_rpcapi
|
||||||
from cinder.common import constants
|
from cinder.common import constants
|
||||||
@ -94,8 +95,8 @@ class ServiceController(wsgi.Controller):
|
|||||||
'status': active, 'state': art,
|
'status': active, 'state': art,
|
||||||
'updated_at': updated_at}
|
'updated_at': updated_at}
|
||||||
|
|
||||||
# On V3.7 we added cluster support
|
# On CLUSTER_SUPPORT we added cluster support
|
||||||
if req.api_version_request.matches('3.7'):
|
if req.api_version_request.matches(mv.CLUSTER_SUPPORT):
|
||||||
ret_fields['cluster'] = svc.cluster_name
|
ret_fields['cluster'] = svc.cluster_name
|
||||||
|
|
||||||
if detailed:
|
if detailed:
|
||||||
@ -125,20 +126,23 @@ class ServiceController(wsgi.Controller):
|
|||||||
raise exception.InvalidInput(ex.msg)
|
raise exception.InvalidInput(ex.msg)
|
||||||
|
|
||||||
def _freeze(self, context, req, body):
|
def _freeze(self, context, req, body):
|
||||||
cluster_name, host = common.get_cluster_host(req, body, '3.26')
|
cluster_name, host = common.get_cluster_host(
|
||||||
|
req, body, mv.REPLICATION_CLUSTER)
|
||||||
return self._volume_api_proxy(self.volume_api.freeze_host, context,
|
return self._volume_api_proxy(self.volume_api.freeze_host, context,
|
||||||
host, cluster_name)
|
host, cluster_name)
|
||||||
|
|
||||||
def _thaw(self, context, req, body):
|
def _thaw(self, context, req, body):
|
||||||
cluster_name, host = common.get_cluster_host(req, body, '3.26')
|
cluster_name, host = common.get_cluster_host(
|
||||||
|
req, body, mv.REPLICATION_CLUSTER)
|
||||||
return self._volume_api_proxy(self.volume_api.thaw_host, context,
|
return self._volume_api_proxy(self.volume_api.thaw_host, context,
|
||||||
host, cluster_name)
|
host, cluster_name)
|
||||||
|
|
||||||
def _failover(self, context, req, body, clustered):
|
def _failover(self, context, req, body, clustered):
|
||||||
# We set version to None to always get the cluster name from the body,
|
# We set version to None to always get the cluster name from the body,
|
||||||
# to False when we don't want to get it, and '3.26' when we only want
|
# to False when we don't want to get it, and REPLICATION_CLUSTER when
|
||||||
# it if the requested version is 3.26 or higher.
|
# we only want it if the requested version is REPLICATION_CLUSTER or
|
||||||
version = '3.26' if clustered else False
|
# higher.
|
||||||
|
version = mv.REPLICATION_CLUSTER if clustered else False
|
||||||
cluster_name, host = common.get_cluster_host(req, body, version)
|
cluster_name, host = common.get_cluster_host(req, body, version)
|
||||||
self._volume_api_proxy(self.volume_api.failover, context, host,
|
self._volume_api_proxy(self.volume_api.failover, context, host,
|
||||||
cluster_name, body.get('backend_id'))
|
cluster_name, body.get('backend_id'))
|
||||||
@ -221,7 +225,7 @@ class ServiceController(wsgi.Controller):
|
|||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
authorize(context, action='update')
|
authorize(context, action='update')
|
||||||
|
|
||||||
support_dynamic_log = req.api_version_request.matches('3.32')
|
support_dynamic_log = req.api_version_request.matches(mv.LOG_LEVEL)
|
||||||
|
|
||||||
ext_loaded = self.ext_mgr.is_loaded('os-extended-services')
|
ext_loaded = self.ext_mgr.is_loaded('os-extended-services')
|
||||||
ret_val = {}
|
ret_val = {}
|
||||||
@ -240,7 +244,8 @@ class ServiceController(wsgi.Controller):
|
|||||||
return self._thaw(context, req, body)
|
return self._thaw(context, req, body)
|
||||||
elif id == "failover_host":
|
elif id == "failover_host":
|
||||||
return self._failover(context, req, body, False)
|
return self._failover(context, req, body, False)
|
||||||
elif req.api_version_request.matches('3.26') and id == 'failover':
|
elif (req.api_version_request.matches(mv.REPLICATION_CLUSTER) and
|
||||||
|
id == 'failover'):
|
||||||
return self._failover(context, req, body, True)
|
return self._failover(context, req, body, True)
|
||||||
elif support_dynamic_log and id == 'set-log':
|
elif support_dynamic_log and id == 'set-log':
|
||||||
return self._set_log(context, body)
|
return self._set_log(context, body)
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder import quota
|
from cinder import quota
|
||||||
|
|
||||||
@ -32,7 +33,8 @@ class UsedLimitsController(wsgi.Controller):
|
|||||||
|
|
||||||
# TODO(wangxiyuan): Support "tenant_id" here to keep the backwards
|
# TODO(wangxiyuan): Support "tenant_id" here to keep the backwards
|
||||||
# compatibility. Remove it once we drop all support for "tenant".
|
# compatibility. Remove it once we drop all support for "tenant".
|
||||||
if req_version.matches(None, "3.38") or not context.is_admin:
|
if (req_version.matches(None, mv.GROUP_REPLICATION) or
|
||||||
|
not context.is_admin):
|
||||||
params.pop('project_id', None)
|
params.pop('project_id', None)
|
||||||
params.pop('tenant_id', None)
|
params.pop('tenant_id', None)
|
||||||
project_id = params.get(
|
project_id = params.get(
|
||||||
|
@ -22,7 +22,7 @@ from six.moves import http_client
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
from cinder.api.openstack import api_version_request
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
@ -271,7 +271,8 @@ class VolumeActionsController(wsgi.Controller):
|
|||||||
|
|
||||||
image_metadata['cinder_encryption_key_id'] = encryption_key_id
|
image_metadata['cinder_encryption_key_id'] = encryption_key_id
|
||||||
|
|
||||||
if req_version >= api_version_request.APIVersionRequest('3.1'):
|
if req_version >= mv.get_api_version(
|
||||||
|
mv.UPLOAD_IMAGE_PARAMS):
|
||||||
|
|
||||||
image_metadata['visibility'] = params.get('visibility', 'private')
|
image_metadata['visibility'] = params.get('visibility', 'private')
|
||||||
image_metadata['protected'] = params.get('protected', 'False')
|
image_metadata['protected'] = params.get('protected', 'False')
|
||||||
@ -321,7 +322,8 @@ class VolumeActionsController(wsgi.Controller):
|
|||||||
raise webob.exc.HTTPBadRequest(explanation=msg)
|
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if req_version.matches("3.42") and volume.status in ['in-use']:
|
if (req_version.matches(mv.VOLUME_EXTEND_INUSE) and
|
||||||
|
volume.status in ['in-use']):
|
||||||
self.volume_api.extend_attached_volume(context, volume, size)
|
self.volume_api.extend_attached_volume(context, volume, size)
|
||||||
else:
|
else:
|
||||||
self.volume_api.extend(context, volume, size)
|
self.volume_api.extend(context, volume, size)
|
||||||
|
@ -18,6 +18,7 @@ from six.moves import http_client
|
|||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
from cinder.api.contrib import resource_common_manage
|
from cinder.api.contrib import resource_common_manage
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v2.views import volumes as volume_views
|
from cinder.api.v2.views import volumes as volume_views
|
||||||
from cinder.api.views import manageable_volumes as list_manageable_view
|
from cinder.api.views import manageable_volumes as list_manageable_view
|
||||||
@ -110,7 +111,8 @@ class VolumeManageController(wsgi.Controller):
|
|||||||
if 'ref' not in volume:
|
if 'ref' not in volume:
|
||||||
raise exception.MissingRequired(element='ref')
|
raise exception.MissingRequired(element='ref')
|
||||||
|
|
||||||
cluster_name, host = common.get_cluster_host(req, volume, '3.16')
|
cluster_name, host = common.get_cluster_host(
|
||||||
|
req, volume, mv.VOLUME_MIGRATE_CLUSTER)
|
||||||
|
|
||||||
LOG.debug('Manage volume request body: %s', body)
|
LOG.debug('Manage volume request body: %s', body)
|
||||||
|
|
||||||
|
172
cinder/api/microversions.py
Normal file
172
cinder/api/microversions.py
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
"""API Microversion definitions.
|
||||||
|
|
||||||
|
All new microversions should have a constant added here to be used throughout
|
||||||
|
the code instead of the specific version number. Until patches land, it's
|
||||||
|
common to end up with merge conflicts with other microversion changes. Merge
|
||||||
|
conflicts will be easier to handle via the microversion constants defined here
|
||||||
|
as the version number will only need to be changed in a single location.
|
||||||
|
|
||||||
|
Actual version numbers should be used:
|
||||||
|
|
||||||
|
* In this file
|
||||||
|
* In cinder/api/openstack/rest_api_version_history.rst
|
||||||
|
* In cinder/api/openstack/api_version_request.py
|
||||||
|
* In release notes describing the new functionality
|
||||||
|
* In updates to api-ref
|
||||||
|
|
||||||
|
Nearly all microversion changes should include changes to all of those
|
||||||
|
locations. Make sure to add relevant documentation, and make sure that
|
||||||
|
documentation includes the final version number used.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from cinder.api.openstack import api_version_request as api_version
|
||||||
|
from cinder import exception
|
||||||
|
|
||||||
|
|
||||||
|
# Add new constants here for each new microversion.
|
||||||
|
|
||||||
|
BASE_VERSION = '3.0'
|
||||||
|
|
||||||
|
UPLOAD_IMAGE_PARAMS = '3.1'
|
||||||
|
|
||||||
|
VOLUME_LIST_BOOTABLE = '3.2'
|
||||||
|
|
||||||
|
MESSAGES = '3.3'
|
||||||
|
|
||||||
|
VOLUME_LIST_GLANCE_METADATA = '3.4'
|
||||||
|
|
||||||
|
MESSAGES_PAGINATION = '3.5'
|
||||||
|
|
||||||
|
CG_UPDATE_BLANK_PROPERTIES = '3.6'
|
||||||
|
|
||||||
|
CLUSTER_SUPPORT = '3.7'
|
||||||
|
|
||||||
|
MANAGE_EXISTING_LIST = '3.8'
|
||||||
|
|
||||||
|
BACKUP_UPDATE = '3.9'
|
||||||
|
|
||||||
|
VOLUME_LIST_GROUP = '3.10'
|
||||||
|
|
||||||
|
GROUP_TYPE = '3.11'
|
||||||
|
|
||||||
|
VOLUME_SUMMARY = '3.12'
|
||||||
|
|
||||||
|
GROUP_VOLUME = '3.13'
|
||||||
|
|
||||||
|
GROUP_SNAPSHOTS = '3.14'
|
||||||
|
|
||||||
|
ETAGS = '3.15'
|
||||||
|
|
||||||
|
VOLUME_MIGRATE_CLUSTER = '3.16'
|
||||||
|
|
||||||
|
MANAGE_EXISTING_CLUSTER = '3.17'
|
||||||
|
|
||||||
|
BACKUP_PROJECT = '3.18'
|
||||||
|
|
||||||
|
GROUP_SNAPSHOT_RESET_STATUS = '3.19'
|
||||||
|
|
||||||
|
GROUP_VOLUME_RESET_STATUS = '3.20'
|
||||||
|
|
||||||
|
VOLUME_DETAIL_PROVIDER_ID = '3.21'
|
||||||
|
|
||||||
|
SNAPSHOT_LIST_METADATA_FILTER = '3.22'
|
||||||
|
|
||||||
|
VOLUME_DELETE_FORCE = '3.23'
|
||||||
|
|
||||||
|
WORKERS_CLEANUP = '3.24'
|
||||||
|
|
||||||
|
GROUP_VOLUME_LIST = '3.25'
|
||||||
|
|
||||||
|
REPLICATION_CLUSTER = '3.26'
|
||||||
|
|
||||||
|
NEW_ATTACH = '3.27'
|
||||||
|
|
||||||
|
POOL_FILTER = '3.28'
|
||||||
|
|
||||||
|
GROUP_SNAPSHOT_PAGINATION = '3.29'
|
||||||
|
|
||||||
|
SNAPSHOT_SORT = '3.30'
|
||||||
|
|
||||||
|
RESOURCE_FILTER = '3.31'
|
||||||
|
|
||||||
|
LOG_LEVEL = '3.32'
|
||||||
|
|
||||||
|
RESOURCE_FILTER_CONFIG = '3.33'
|
||||||
|
|
||||||
|
LIKE_FILTER = '3.34'
|
||||||
|
|
||||||
|
POOL_TYPE_FILTER = '3.35'
|
||||||
|
|
||||||
|
VOLUME_SUMMARY_METADATA = '3.36'
|
||||||
|
|
||||||
|
BACKUP_SORT_NAME = '3.37'
|
||||||
|
|
||||||
|
GROUP_REPLICATION = '3.38'
|
||||||
|
|
||||||
|
LIMITS_ADMIN_FILTER = '3.39'
|
||||||
|
|
||||||
|
VOLUME_REVERT = '3.40'
|
||||||
|
|
||||||
|
SNAPSHOT_LIST_USER_ID = '3.41'
|
||||||
|
|
||||||
|
VOLUME_EXTEND_INUSE = '3.42'
|
||||||
|
|
||||||
|
BACKUP_METADATA = '3.43'
|
||||||
|
|
||||||
|
NEW_ATTACH_COMPLETION = '3.44'
|
||||||
|
|
||||||
|
|
||||||
|
def get_mv_header(version):
|
||||||
|
"""Gets a formatted HTTP microversion header.
|
||||||
|
|
||||||
|
:param version: The microversion needed.
|
||||||
|
:return: A tuple containing the microversion header with the
|
||||||
|
requested version value.
|
||||||
|
"""
|
||||||
|
return {'OpenStack-API-Version':
|
||||||
|
'volume %s' % version}
|
||||||
|
|
||||||
|
|
||||||
|
def get_api_version(version):
|
||||||
|
"""Gets a ``APIVersionRequest`` instance.
|
||||||
|
|
||||||
|
:param version: The microversion needed.
|
||||||
|
:return: The ``APIVersionRequest`` instance.
|
||||||
|
"""
|
||||||
|
return api_version.APIVersionRequest(version)
|
||||||
|
|
||||||
|
|
||||||
|
def get_prior_version(version):
|
||||||
|
"""Gets the microversion before the given version.
|
||||||
|
|
||||||
|
Mostly useful for testing boundaries. This gets the microversion defined
|
||||||
|
just prior to the given version.
|
||||||
|
|
||||||
|
:param version: The version of interest.
|
||||||
|
:return: The version just prior to the given version.
|
||||||
|
"""
|
||||||
|
parts = version.split('.')
|
||||||
|
|
||||||
|
if len(parts) != 2 or parts[0] != '3':
|
||||||
|
raise exception.InvalidInput(reason='Version %s is not a valid '
|
||||||
|
'microversion format.' % version)
|
||||||
|
|
||||||
|
minor = int(parts[1]) - 1
|
||||||
|
|
||||||
|
if minor < 0:
|
||||||
|
# What's your problem? Are you trying to be difficult?
|
||||||
|
minor = 0
|
||||||
|
|
||||||
|
return '%s.%s' % (parts[0], minor)
|
@ -116,6 +116,7 @@ REST_API_VERSION_HISTORY = """
|
|||||||
_MIN_API_VERSION = "3.0"
|
_MIN_API_VERSION = "3.0"
|
||||||
_MAX_API_VERSION = "3.44"
|
_MAX_API_VERSION = "3.44"
|
||||||
_LEGACY_API_VERSION2 = "2.0"
|
_LEGACY_API_VERSION2 = "2.0"
|
||||||
|
UPDATED = "2017-09-19T20:18:14Z"
|
||||||
|
|
||||||
|
|
||||||
# NOTE(cyeoh): min and max versions declared as functions so we can
|
# NOTE(cyeoh): min and max versions declared as functions so we can
|
||||||
|
@ -95,7 +95,7 @@ class VolumeController(wsgi.Controller):
|
|||||||
filters = params
|
filters = params
|
||||||
|
|
||||||
# NOTE(wanghao): Always removing glance_metadata since we support it
|
# NOTE(wanghao): Always removing glance_metadata since we support it
|
||||||
# only in API version >= 3.4.
|
# only in API version >= VOLUME_LIST_GLANCE_METADATA.
|
||||||
filters.pop('glance_metadata', None)
|
filters.pop('glance_metadata', None)
|
||||||
utils.remove_invalid_filter_options(context,
|
utils.remove_invalid_filter_options(context,
|
||||||
filters,
|
filters,
|
||||||
|
@ -16,6 +16,7 @@ from oslo_log import log as logging
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v3.views import attachments as attachment_views
|
from cinder.api.v3.views import attachments as attachment_views
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -26,8 +27,6 @@ from cinder.volume import api as volume_api
|
|||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
API_VERSION = '3.27'
|
|
||||||
ATTACHMENT_COMPLETION_VERSION = '3.44'
|
|
||||||
|
|
||||||
|
|
||||||
class AttachmentsController(wsgi.Controller):
|
class AttachmentsController(wsgi.Controller):
|
||||||
@ -43,20 +42,20 @@ class AttachmentsController(wsgi.Controller):
|
|||||||
self.ext_mgr = ext_mgr
|
self.ext_mgr = ext_mgr
|
||||||
super(AttachmentsController, self).__init__()
|
super(AttachmentsController, self).__init__()
|
||||||
|
|
||||||
@wsgi.Controller.api_version(API_VERSION)
|
@wsgi.Controller.api_version(mv.NEW_ATTACH)
|
||||||
def show(self, req, id):
|
def show(self, req, id):
|
||||||
"""Return data about the given attachment."""
|
"""Return data about the given attachment."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
attachment = objects.VolumeAttachment.get_by_id(context, id)
|
attachment = objects.VolumeAttachment.get_by_id(context, id)
|
||||||
return attachment_views.ViewBuilder.detail(attachment)
|
return attachment_views.ViewBuilder.detail(attachment)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(API_VERSION)
|
@wsgi.Controller.api_version(mv.NEW_ATTACH)
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
"""Return a summary list of attachments."""
|
"""Return a summary list of attachments."""
|
||||||
attachments = self._items(req)
|
attachments = self._items(req)
|
||||||
return attachment_views.ViewBuilder.list(attachments)
|
return attachment_views.ViewBuilder.list(attachments)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(API_VERSION)
|
@wsgi.Controller.api_version(mv.NEW_ATTACH)
|
||||||
def detail(self, req):
|
def detail(self, req):
|
||||||
"""Return a detailed list of attachments."""
|
"""Return a detailed list of attachments."""
|
||||||
attachments = self._items(req)
|
attachments = self._items(req)
|
||||||
@ -94,7 +93,7 @@ class AttachmentsController(wsgi.Controller):
|
|||||||
marker=marker, limit=limit, offset=offset, sort_keys=sort_keys,
|
marker=marker, limit=limit, offset=offset, sort_keys=sort_keys,
|
||||||
sort_direction=sort_dirs)
|
sort_direction=sort_dirs)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(API_VERSION)
|
@wsgi.Controller.api_version(mv.NEW_ATTACH)
|
||||||
@wsgi.response(202)
|
@wsgi.response(202)
|
||||||
def create(self, req, body):
|
def create(self, req, body):
|
||||||
"""Create an attachment.
|
"""Create an attachment.
|
||||||
@ -192,7 +191,7 @@ class AttachmentsController(wsgi.Controller):
|
|||||||
raise webob.exc.HTTPInternalServerError(explanation=err_msg)
|
raise webob.exc.HTTPInternalServerError(explanation=err_msg)
|
||||||
return attachment_views.ViewBuilder.detail(attachment_ref)
|
return attachment_views.ViewBuilder.detail(attachment_ref)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(API_VERSION)
|
@wsgi.Controller.api_version(mv.NEW_ATTACH)
|
||||||
def update(self, req, id, body):
|
def update(self, req, id, body):
|
||||||
"""Update an attachment record.
|
"""Update an attachment record.
|
||||||
|
|
||||||
@ -252,7 +251,7 @@ class AttachmentsController(wsgi.Controller):
|
|||||||
# or a dict?
|
# or a dict?
|
||||||
return attachment_views.ViewBuilder.detail(attachment_ref)
|
return attachment_views.ViewBuilder.detail(attachment_ref)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(API_VERSION)
|
@wsgi.Controller.api_version(mv.NEW_ATTACH)
|
||||||
def delete(self, req, id):
|
def delete(self, req, id):
|
||||||
"""Delete an attachment.
|
"""Delete an attachment.
|
||||||
|
|
||||||
@ -268,7 +267,7 @@ class AttachmentsController(wsgi.Controller):
|
|||||||
return attachment_views.ViewBuilder.list(attachments)
|
return attachment_views.ViewBuilder.list(attachments)
|
||||||
|
|
||||||
@wsgi.response(202)
|
@wsgi.response(202)
|
||||||
@wsgi.Controller.api_version(ATTACHMENT_COMPLETION_VERSION)
|
@wsgi.Controller.api_version(mv.NEW_ATTACH_COMPLETION)
|
||||||
@wsgi.action('os-complete')
|
@wsgi.action('os-complete')
|
||||||
def complete(self, req, id, body):
|
def complete(self, req, id, body):
|
||||||
"""Mark a volume attachment process as completed (in-use)."""
|
"""Mark a volume attachment process as completed (in-use)."""
|
||||||
|
@ -19,22 +19,20 @@ from oslo_log import log as logging
|
|||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from cinder.api.contrib import backups as backups_v2
|
from cinder.api.contrib import backups as backups_v2
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.backup import api as backup_api
|
from cinder.backup import api as backup_api
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
|
|
||||||
|
|
||||||
BACKUP_UPDATE_MICRO_VERSION = '3.9'
|
|
||||||
BACKUP_TENANT_MICRO_VERSION = '3.18'
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class BackupsController(backups_v2.BackupsController):
|
class BackupsController(backups_v2.BackupsController):
|
||||||
"""The backups API controller for the OpenStack API V3."""
|
"""The backups API controller for the OpenStack API V3."""
|
||||||
|
|
||||||
@wsgi.Controller.api_version(BACKUP_UPDATE_MICRO_VERSION)
|
@wsgi.Controller.api_version(mv.BACKUP_UPDATE)
|
||||||
def update(self, req, id, body):
|
def update(self, req, id, body):
|
||||||
"""Update a backup."""
|
"""Update a backup."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
@ -50,7 +48,8 @@ class BackupsController(backups_v2.BackupsController):
|
|||||||
if 'description' in backup_update:
|
if 'description' in backup_update:
|
||||||
update_dict['display_description'] = (
|
update_dict['display_description'] = (
|
||||||
backup_update.pop('description'))
|
backup_update.pop('description'))
|
||||||
if req_version.matches('3.43') and 'metadata' in backup_update:
|
if (req_version.matches(
|
||||||
|
mv.BACKUP_METADATA) and 'metadata' in backup_update):
|
||||||
update_dict['metadata'] = backup_update.pop('metadata')
|
update_dict['metadata'] = backup_update.pop('metadata')
|
||||||
# Check no unsupported fields.
|
# Check no unsupported fields.
|
||||||
if backup_update:
|
if backup_update:
|
||||||
@ -77,7 +76,7 @@ class BackupsController(backups_v2.BackupsController):
|
|||||||
req.cache_db_backup(backup)
|
req.cache_db_backup(backup)
|
||||||
|
|
||||||
resp_backup = self._view_builder.detail(req, backup)
|
resp_backup = self._view_builder.detail(req, backup)
|
||||||
if req_version.matches(BACKUP_TENANT_MICRO_VERSION):
|
if req_version.matches(mv.BACKUP_PROJECT):
|
||||||
try:
|
try:
|
||||||
backup_api.check_policy(context, 'backup_project_attribute')
|
backup_api.check_policy(context, 'backup_project_attribute')
|
||||||
self._add_backup_project_attribute(req, resp_backup['backup'])
|
self._add_backup_project_attribute(req, resp_backup['backup'])
|
||||||
@ -90,7 +89,7 @@ class BackupsController(backups_v2.BackupsController):
|
|||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
req_version = req.api_version_request
|
req_version = req.api_version_request
|
||||||
|
|
||||||
if req_version.matches(BACKUP_TENANT_MICRO_VERSION):
|
if req_version.matches(mv.BACKUP_PROJECT):
|
||||||
try:
|
try:
|
||||||
backup_api.check_policy(context, 'backup_project_attribute')
|
backup_api.check_policy(context, 'backup_project_attribute')
|
||||||
for bak in resp_backup['backups']:
|
for bak in resp_backup['backups']:
|
||||||
@ -100,7 +99,7 @@ class BackupsController(backups_v2.BackupsController):
|
|||||||
return resp_backup
|
return resp_backup
|
||||||
|
|
||||||
def _convert_sort_name(self, req_version, sort_keys):
|
def _convert_sort_name(self, req_version, sort_keys):
|
||||||
if req_version.matches("3.37") and 'name' in sort_keys:
|
if req_version.matches(mv.BACKUP_SORT_NAME) and 'name' in sort_keys:
|
||||||
sort_keys[sort_keys.index('name')] = 'display_name'
|
sort_keys[sort_keys.index('name')] = 'display_name'
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v3.views import clusters as clusters_view
|
from cinder.api.v3.views import clusters as clusters_view
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -21,10 +22,6 @@ from cinder import objects
|
|||||||
from cinder import utils
|
from cinder import utils
|
||||||
|
|
||||||
|
|
||||||
CLUSTER_MICRO_VERSION = '3.7'
|
|
||||||
REPLICATION_DATA_MICRO_VERSION = '3.26'
|
|
||||||
|
|
||||||
|
|
||||||
class ClusterController(wsgi.Controller):
|
class ClusterController(wsgi.Controller):
|
||||||
allowed_list_keys = {'name', 'binary', 'is_up', 'disabled', 'num_hosts',
|
allowed_list_keys = {'name', 'binary', 'is_up', 'disabled', 'num_hosts',
|
||||||
'num_down_hosts', 'binary', 'replication_status',
|
'num_down_hosts', 'binary', 'replication_status',
|
||||||
@ -33,7 +30,7 @@ class ClusterController(wsgi.Controller):
|
|||||||
|
|
||||||
policy_checker = wsgi.Controller.get_policy_checker('clusters')
|
policy_checker = wsgi.Controller.get_policy_checker('clusters')
|
||||||
|
|
||||||
@wsgi.Controller.api_version(CLUSTER_MICRO_VERSION)
|
@wsgi.Controller.api_version(mv.CLUSTER_SUPPORT)
|
||||||
def show(self, req, id, binary='cinder-volume'):
|
def show(self, req, id, binary='cinder-volume'):
|
||||||
"""Return data for a given cluster name with optional binary."""
|
"""Return data for a given cluster name with optional binary."""
|
||||||
# Let the wsgi middleware convert NotAuthorized exceptions
|
# Let the wsgi middleware convert NotAuthorized exceptions
|
||||||
@ -42,10 +39,10 @@ class ClusterController(wsgi.Controller):
|
|||||||
cluster = objects.Cluster.get_by_id(context, None, binary=binary,
|
cluster = objects.Cluster.get_by_id(context, None, binary=binary,
|
||||||
name=id, services_summary=True)
|
name=id, services_summary=True)
|
||||||
replication_data = req.api_version_request.matches(
|
replication_data = req.api_version_request.matches(
|
||||||
REPLICATION_DATA_MICRO_VERSION)
|
mv.REPLICATION_CLUSTER)
|
||||||
return clusters_view.ViewBuilder.detail(cluster, replication_data)
|
return clusters_view.ViewBuilder.detail(cluster, replication_data)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(CLUSTER_MICRO_VERSION)
|
@wsgi.Controller.api_version(mv.CLUSTER_SUPPORT)
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
"""Return a non detailed list of all existing clusters.
|
"""Return a non detailed list of all existing clusters.
|
||||||
|
|
||||||
@ -53,7 +50,7 @@ class ClusterController(wsgi.Controller):
|
|||||||
"""
|
"""
|
||||||
return self._get_clusters(req, detail=False)
|
return self._get_clusters(req, detail=False)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(CLUSTER_MICRO_VERSION)
|
@wsgi.Controller.api_version(mv.CLUSTER_SUPPORT)
|
||||||
def detail(self, req):
|
def detail(self, req):
|
||||||
"""Return a detailed list of all existing clusters.
|
"""Return a detailed list of all existing clusters.
|
||||||
|
|
||||||
@ -65,7 +62,7 @@ class ClusterController(wsgi.Controller):
|
|||||||
# Let the wsgi middleware convert NotAuthorized exceptions
|
# Let the wsgi middleware convert NotAuthorized exceptions
|
||||||
context = self.policy_checker(req, 'get_all')
|
context = self.policy_checker(req, 'get_all')
|
||||||
replication_data = req.api_version_request.matches(
|
replication_data = req.api_version_request.matches(
|
||||||
REPLICATION_DATA_MICRO_VERSION)
|
mv.REPLICATION_CLUSTER)
|
||||||
filters = dict(req.GET)
|
filters = dict(req.GET)
|
||||||
allowed = self.allowed_list_keys
|
allowed = self.allowed_list_keys
|
||||||
if not replication_data:
|
if not replication_data:
|
||||||
@ -89,7 +86,7 @@ class ClusterController(wsgi.Controller):
|
|||||||
return clusters_view.ViewBuilder.list(clusters, detail,
|
return clusters_view.ViewBuilder.list(clusters, detail,
|
||||||
replication_data)
|
replication_data)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(CLUSTER_MICRO_VERSION)
|
@wsgi.Controller.api_version(mv.CLUSTER_SUPPORT)
|
||||||
def update(self, req, id, body):
|
def update(self, req, id, body):
|
||||||
"""Enable/Disable scheduling for a cluster."""
|
"""Enable/Disable scheduling for a cluster."""
|
||||||
# NOTE(geguileo): This method tries to be consistent with services
|
# NOTE(geguileo): This method tries to be consistent with services
|
||||||
@ -123,7 +120,7 @@ class ClusterController(wsgi.Controller):
|
|||||||
|
|
||||||
# We return summary data plus the disabled reason
|
# We return summary data plus the disabled reason
|
||||||
replication_data = req.api_version_request.matches(
|
replication_data = req.api_version_request.matches(
|
||||||
REPLICATION_DATA_MICRO_VERSION)
|
mv.REPLICATION_CLUSTER)
|
||||||
ret_val = clusters_view.ViewBuilder.summary(cluster, replication_data)
|
ret_val = clusters_view.ViewBuilder.summary(cluster, replication_data)
|
||||||
ret_val['cluster']['disabled_reason'] = disabled_reason
|
ret_val['cluster']['disabled_reason'] = disabled_reason
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import webob
|
|||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from cinder.api.contrib import consistencygroups as cg_v2
|
from cinder.api.contrib import consistencygroups as cg_v2
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
|
|
||||||
@ -30,7 +31,8 @@ class ConsistencyGroupsController(cg_v2.ConsistencyGroupsController):
|
|||||||
|
|
||||||
def _check_update_parameters_v3(self, req, name, description, add_volumes,
|
def _check_update_parameters_v3(self, req, name, description, add_volumes,
|
||||||
remove_volumes):
|
remove_volumes):
|
||||||
allow_empty = req.api_version_request.matches('3.6', None)
|
allow_empty = req.api_version_request.matches(
|
||||||
|
mv.CG_UPDATE_BLANK_PROPERTIES, None)
|
||||||
if allow_empty:
|
if allow_empty:
|
||||||
if (name is None and description is None
|
if (name is None and description is None
|
||||||
and not add_volumes and not remove_volumes):
|
and not add_volumes and not remove_volumes):
|
||||||
|
@ -22,6 +22,7 @@ import webob
|
|||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v3.views import group_snapshots as group_snapshot_views
|
from cinder.api.v3.views import group_snapshots as group_snapshot_views
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -32,8 +33,6 @@ from cinder.volume import group_types
|
|||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
GROUP_SNAPSHOT_API_VERSION = '3.14'
|
|
||||||
|
|
||||||
|
|
||||||
class GroupSnapshotsController(wsgi.Controller):
|
class GroupSnapshotsController(wsgi.Controller):
|
||||||
"""The group_snapshots API controller for the OpenStack API."""
|
"""The group_snapshots API controller for the OpenStack API."""
|
||||||
@ -52,7 +51,7 @@ class GroupSnapshotsController(wsgi.Controller):
|
|||||||
% {'group_type': group_type_id})
|
% {'group_type': group_type_id})
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_SNAPSHOT_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_SNAPSHOTS)
|
||||||
def show(self, req, id):
|
def show(self, req, id):
|
||||||
"""Return data about the given group_snapshot."""
|
"""Return data about the given group_snapshot."""
|
||||||
LOG.debug('show called for member %s', id)
|
LOG.debug('show called for member %s', id)
|
||||||
@ -66,7 +65,7 @@ class GroupSnapshotsController(wsgi.Controller):
|
|||||||
|
|
||||||
return self._view_builder.detail(req, group_snapshot)
|
return self._view_builder.detail(req, group_snapshot)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_SNAPSHOT_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_SNAPSHOTS)
|
||||||
def delete(self, req, id):
|
def delete(self, req, id):
|
||||||
"""Delete a group_snapshot."""
|
"""Delete a group_snapshot."""
|
||||||
LOG.debug('delete called for member %s', id)
|
LOG.debug('delete called for member %s', id)
|
||||||
@ -93,12 +92,12 @@ class GroupSnapshotsController(wsgi.Controller):
|
|||||||
|
|
||||||
return webob.Response(status_int=http_client.ACCEPTED)
|
return webob.Response(status_int=http_client.ACCEPTED)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_SNAPSHOT_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_SNAPSHOTS)
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
"""Returns a summary list of group_snapshots."""
|
"""Returns a summary list of group_snapshots."""
|
||||||
return self._get_group_snapshots(req, is_detail=False)
|
return self._get_group_snapshots(req, is_detail=False)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_SNAPSHOT_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_SNAPSHOTS)
|
||||||
def detail(self, req):
|
def detail(self, req):
|
||||||
"""Returns a detailed list of group_snapshots."""
|
"""Returns a detailed list of group_snapshots."""
|
||||||
return self._get_group_snapshots(req, is_detail=True)
|
return self._get_group_snapshots(req, is_detail=True)
|
||||||
@ -109,14 +108,14 @@ class GroupSnapshotsController(wsgi.Controller):
|
|||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
req_version = req.api_version_request
|
req_version = req.api_version_request
|
||||||
filters = marker = limit = offset = sort_keys = sort_dirs = None
|
filters = marker = limit = offset = sort_keys = sort_dirs = None
|
||||||
if req_version.matches("3.29"):
|
if req_version.matches(mv.GROUP_SNAPSHOT_PAGINATION):
|
||||||
filters = req.params.copy()
|
filters = req.params.copy()
|
||||||
marker, limit, offset = common.get_pagination_params(filters)
|
marker, limit, offset = common.get_pagination_params(filters)
|
||||||
sort_keys, sort_dirs = common.get_sort_params(filters)
|
sort_keys, sort_dirs = common.get_sort_params(filters)
|
||||||
|
|
||||||
if req_version.matches(common.FILTERING_VERSION):
|
if req_version.matches(mv.RESOURCE_FILTER):
|
||||||
support_like = (True if req_version.matches(
|
support_like = (True if req_version.matches(
|
||||||
common.LIKE_FILTER_VERSION) else False)
|
mv.LIKE_FILTER) else False)
|
||||||
common.reject_invalid_filters(context, filters, 'group_snapshot',
|
common.reject_invalid_filters(context, filters, 'group_snapshot',
|
||||||
support_like)
|
support_like)
|
||||||
|
|
||||||
@ -145,7 +144,7 @@ class GroupSnapshotsController(wsgi.Controller):
|
|||||||
group_snapshots['group_snapshots'] = new_group_snapshots
|
group_snapshots['group_snapshots'] = new_group_snapshots
|
||||||
return group_snapshots
|
return group_snapshots
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_SNAPSHOT_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_SNAPSHOTS)
|
||||||
@wsgi.response(http_client.ACCEPTED)
|
@wsgi.response(http_client.ACCEPTED)
|
||||||
def create(self, req, body):
|
def create(self, req, body):
|
||||||
"""Create a new group_snapshot."""
|
"""Create a new group_snapshot."""
|
||||||
@ -183,7 +182,7 @@ class GroupSnapshotsController(wsgi.Controller):
|
|||||||
|
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.19')
|
@wsgi.Controller.api_version(mv.GROUP_SNAPSHOT_RESET_STATUS)
|
||||||
@wsgi.action("reset_status")
|
@wsgi.action("reset_status")
|
||||||
def reset_status(self, req, id, body):
|
def reset_status(self, req, id, body):
|
||||||
return self._reset_status(req, id, body)
|
return self._reset_status(req, id, body)
|
||||||
|
@ -18,6 +18,7 @@ from six.moves import http_client
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder import db
|
from cinder import db
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -51,7 +52,7 @@ class GroupTypeSpecsController(wsgi.Controller):
|
|||||||
except exception.GroupTypeNotFound as ex:
|
except exception.GroupTypeNotFound as ex:
|
||||||
raise webob.exc.HTTPNotFound(explanation=ex.msg)
|
raise webob.exc.HTTPNotFound(explanation=ex.msg)
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.11')
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
def index(self, req, group_type_id):
|
def index(self, req, group_type_id):
|
||||||
"""Returns the list of group specs for a given group type."""
|
"""Returns the list of group specs for a given group type."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
@ -59,7 +60,7 @@ class GroupTypeSpecsController(wsgi.Controller):
|
|||||||
self._check_type(context, group_type_id)
|
self._check_type(context, group_type_id)
|
||||||
return self._get_group_specs(context, group_type_id)
|
return self._get_group_specs(context, group_type_id)
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.11')
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
@wsgi.response(http_client.ACCEPTED)
|
@wsgi.response(http_client.ACCEPTED)
|
||||||
def create(self, req, group_type_id, body=None):
|
def create(self, req, group_type_id, body=None):
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
@ -80,7 +81,7 @@ class GroupTypeSpecsController(wsgi.Controller):
|
|||||||
notifier_info)
|
notifier_info)
|
||||||
return body
|
return body
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.11')
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
def update(self, req, group_type_id, id, body=None):
|
def update(self, req, group_type_id, id, body=None):
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
self._check_policy(context)
|
self._check_policy(context)
|
||||||
@ -108,7 +109,7 @@ class GroupTypeSpecsController(wsgi.Controller):
|
|||||||
notifier_info)
|
notifier_info)
|
||||||
return body
|
return body
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.11')
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
def show(self, req, group_type_id, id):
|
def show(self, req, group_type_id, id):
|
||||||
"""Return a single extra spec item."""
|
"""Return a single extra spec item."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
@ -123,7 +124,7 @@ class GroupTypeSpecsController(wsgi.Controller):
|
|||||||
"%(id)s.") % ({'type_id': group_type_id, 'id': id})
|
"%(id)s.") % ({'type_id': group_type_id, 'id': id})
|
||||||
raise webob.exc.HTTPNotFound(explanation=msg)
|
raise webob.exc.HTTPNotFound(explanation=msg)
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.11')
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
def delete(self, req, group_type_id, id):
|
def delete(self, req, group_type_id, id):
|
||||||
"""Deletes an existing group spec."""
|
"""Deletes an existing group spec."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
|
@ -21,6 +21,7 @@ import webob
|
|||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v3.views import group_types as views_types
|
from cinder.api.v3.views import group_types as views_types
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -55,7 +56,7 @@ class GroupTypesController(wsgi.Controller):
|
|||||||
payload = dict(group_types=group_type)
|
payload = dict(group_types=group_type)
|
||||||
rpc.get_notifier('groupType').info(context, method, payload)
|
rpc.get_notifier('groupType').info(context, method, payload)
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.11')
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
@wsgi.response(http_client.ACCEPTED)
|
@wsgi.response(http_client.ACCEPTED)
|
||||||
def create(self, req, body):
|
def create(self, req, body):
|
||||||
"""Creates a new group type."""
|
"""Creates a new group type."""
|
||||||
@ -103,7 +104,7 @@ class GroupTypesController(wsgi.Controller):
|
|||||||
|
|
||||||
return self._view_builder.show(req, grp_type)
|
return self._view_builder.show(req, grp_type)
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.11')
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
def update(self, req, id, body):
|
def update(self, req, id, body):
|
||||||
# Update description for a given group type.
|
# Update description for a given group type.
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
@ -163,7 +164,7 @@ class GroupTypesController(wsgi.Controller):
|
|||||||
|
|
||||||
return self._view_builder.show(req, grp_type)
|
return self._view_builder.show(req, grp_type)
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.11')
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
def delete(self, req, id):
|
def delete(self, req, id):
|
||||||
"""Deletes an existing group type."""
|
"""Deletes an existing group type."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
@ -186,14 +187,14 @@ class GroupTypesController(wsgi.Controller):
|
|||||||
|
|
||||||
return webob.Response(status_int=http_client.ACCEPTED)
|
return webob.Response(status_int=http_client.ACCEPTED)
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.11')
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
"""Returns the list of group types."""
|
"""Returns the list of group types."""
|
||||||
limited_types = self._get_group_types(req)
|
limited_types = self._get_group_types(req)
|
||||||
req.cache_resource(limited_types, name='group_types')
|
req.cache_resource(limited_types, name='group_types')
|
||||||
return self._view_builder.index(req, limited_types)
|
return self._view_builder.index(req, limited_types)
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.11')
|
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||||
def show(self, req, id):
|
def show(self, req, id):
|
||||||
"""Return a single group type item."""
|
"""Return a single group type item."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
|
@ -22,6 +22,7 @@ import webob
|
|||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v3.views import groups as views_groups
|
from cinder.api.v3.views import groups as views_groups
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -32,10 +33,6 @@ from cinder.volume import group_types
|
|||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
GROUP_API_VERSION = '3.13'
|
|
||||||
GROUP_CREATE_FROM_SRC_API_VERSION = '3.14'
|
|
||||||
GROUP_REPLICATION_API_VERSION = '3.38'
|
|
||||||
|
|
||||||
|
|
||||||
class GroupsController(wsgi.Controller):
|
class GroupsController(wsgi.Controller):
|
||||||
"""The groups API controller for the OpenStack API."""
|
"""The groups API controller for the OpenStack API."""
|
||||||
@ -53,7 +50,7 @@ class GroupsController(wsgi.Controller):
|
|||||||
"CG APIs.") % {'group_type': group_type_id}
|
"CG APIs.") % {'group_type': group_type_id}
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_VOLUME)
|
||||||
def show(self, req, id):
|
def show(self, req, id):
|
||||||
"""Return data about the given group."""
|
"""Return data about the given group."""
|
||||||
LOG.debug('show called for member %s', id)
|
LOG.debug('show called for member %s', id)
|
||||||
@ -68,7 +65,7 @@ class GroupsController(wsgi.Controller):
|
|||||||
|
|
||||||
return self._view_builder.detail(req, group)
|
return self._view_builder.detail(req, group)
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.20')
|
@wsgi.Controller.api_version(mv.GROUP_VOLUME_RESET_STATUS)
|
||||||
@wsgi.action("reset_status")
|
@wsgi.action("reset_status")
|
||||||
def reset_status(self, req, id, body):
|
def reset_status(self, req, id, body):
|
||||||
return self._reset_status(req, id, body)
|
return self._reset_status(req, id, body)
|
||||||
@ -109,7 +106,7 @@ class GroupsController(wsgi.Controller):
|
|||||||
raise exc.HTTPBadRequest(explanation=error.msg)
|
raise exc.HTTPBadRequest(explanation=error.msg)
|
||||||
return webob.Response(status_int=http_client.ACCEPTED)
|
return webob.Response(status_int=http_client.ACCEPTED)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_VOLUME)
|
||||||
@wsgi.action("delete")
|
@wsgi.action("delete")
|
||||||
def delete_group(self, req, id, body):
|
def delete_group(self, req, id, body):
|
||||||
return self._delete(req, id, body)
|
return self._delete(req, id, body)
|
||||||
@ -150,12 +147,12 @@ class GroupsController(wsgi.Controller):
|
|||||||
|
|
||||||
return webob.Response(status_int=http_client.ACCEPTED)
|
return webob.Response(status_int=http_client.ACCEPTED)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_VOLUME)
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
"""Returns a summary list of groups."""
|
"""Returns a summary list of groups."""
|
||||||
return self._get_groups(req, is_detail=False)
|
return self._get_groups(req, is_detail=False)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_VOLUME)
|
||||||
def detail(self, req):
|
def detail(self, req):
|
||||||
"""Returns a detailed list of groups."""
|
"""Returns a detailed list of groups."""
|
||||||
return self._get_groups(req, is_detail=True)
|
return self._get_groups(req, is_detail=True)
|
||||||
@ -169,9 +166,9 @@ class GroupsController(wsgi.Controller):
|
|||||||
sort_keys, sort_dirs = common.get_sort_params(filters)
|
sort_keys, sort_dirs = common.get_sort_params(filters)
|
||||||
|
|
||||||
filters.pop('list_volume', None)
|
filters.pop('list_volume', None)
|
||||||
if api_version.matches(common.FILTERING_VERSION):
|
if api_version.matches(mv.RESOURCE_FILTER):
|
||||||
support_like = (True if api_version.matches(
|
support_like = (True if api_version.matches(
|
||||||
common.LIKE_FILTER_VERSION) else False)
|
mv.LIKE_FILTER) else False)
|
||||||
common.reject_invalid_filters(context, filters, 'group',
|
common.reject_invalid_filters(context, filters, 'group',
|
||||||
support_like)
|
support_like)
|
||||||
|
|
||||||
@ -197,7 +194,7 @@ class GroupsController(wsgi.Controller):
|
|||||||
req, new_groups)
|
req, new_groups)
|
||||||
return groups
|
return groups
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_VOLUME)
|
||||||
@wsgi.response(http_client.ACCEPTED)
|
@wsgi.response(http_client.ACCEPTED)
|
||||||
def create(self, req, body):
|
def create(self, req, body):
|
||||||
"""Create a new group."""
|
"""Create a new group."""
|
||||||
@ -243,7 +240,7 @@ class GroupsController(wsgi.Controller):
|
|||||||
retval = self._view_builder.summary(req, new_group)
|
retval = self._view_builder.summary(req, new_group)
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_CREATE_FROM_SRC_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_SNAPSHOTS)
|
||||||
@wsgi.action("create-from-src")
|
@wsgi.action("create-from-src")
|
||||||
@wsgi.response(http_client.ACCEPTED)
|
@wsgi.response(http_client.ACCEPTED)
|
||||||
def create_from_src(self, req, body):
|
def create_from_src(self, req, body):
|
||||||
@ -308,7 +305,7 @@ class GroupsController(wsgi.Controller):
|
|||||||
retval = self._view_builder.summary(req, new_group)
|
retval = self._view_builder.summary(req, new_group)
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_VOLUME)
|
||||||
def update(self, req, id, body):
|
def update(self, req, id, body):
|
||||||
"""Update the group.
|
"""Update the group.
|
||||||
|
|
||||||
@ -373,7 +370,7 @@ class GroupsController(wsgi.Controller):
|
|||||||
|
|
||||||
return webob.Response(status_int=http_client.ACCEPTED)
|
return webob.Response(status_int=http_client.ACCEPTED)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_REPLICATION_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_REPLICATION)
|
||||||
@wsgi.action("enable_replication")
|
@wsgi.action("enable_replication")
|
||||||
def enable_replication(self, req, id, body):
|
def enable_replication(self, req, id, body):
|
||||||
"""Enables replications for a group."""
|
"""Enables replications for a group."""
|
||||||
@ -397,7 +394,7 @@ class GroupsController(wsgi.Controller):
|
|||||||
|
|
||||||
return webob.Response(status_int=202)
|
return webob.Response(status_int=202)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_REPLICATION_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_REPLICATION)
|
||||||
@wsgi.action("disable_replication")
|
@wsgi.action("disable_replication")
|
||||||
def disable_replication(self, req, id, body):
|
def disable_replication(self, req, id, body):
|
||||||
"""Disables replications for a group."""
|
"""Disables replications for a group."""
|
||||||
@ -421,7 +418,7 @@ class GroupsController(wsgi.Controller):
|
|||||||
|
|
||||||
return webob.Response(status_int=202)
|
return webob.Response(status_int=202)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_REPLICATION_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_REPLICATION)
|
||||||
@wsgi.action("failover_replication")
|
@wsgi.action("failover_replication")
|
||||||
def failover_replication(self, req, id, body):
|
def failover_replication(self, req, id, body):
|
||||||
"""Fails over replications for a group."""
|
"""Fails over replications for a group."""
|
||||||
@ -457,7 +454,7 @@ class GroupsController(wsgi.Controller):
|
|||||||
|
|
||||||
return webob.Response(status_int=202)
|
return webob.Response(status_int=202)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(GROUP_REPLICATION_API_VERSION)
|
@wsgi.Controller.api_version(mv.GROUP_REPLICATION)
|
||||||
@wsgi.action("list_replication_targets")
|
@wsgi.action("list_replication_targets")
|
||||||
def list_replication_targets(self, req, id, body):
|
def list_replication_targets(self, req, id, body):
|
||||||
"""List replication targets for a group."""
|
"""List replication targets for a group."""
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
"""The limits V3 api."""
|
"""The limits V3 api."""
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v2 import limits as limits_v2
|
from cinder.api.v2 import limits as limits_v2
|
||||||
from cinder.api.views import limits as limits_views
|
from cinder.api.views import limits as limits_views
|
||||||
@ -32,7 +33,8 @@ class LimitsController(limits_v2.LimitsController):
|
|||||||
|
|
||||||
# TODO(wangxiyuan): Support "tenant_id" here to keep the backwards
|
# TODO(wangxiyuan): Support "tenant_id" here to keep the backwards
|
||||||
# compatibility. Remove it once we drop all support for "tenant".
|
# compatibility. Remove it once we drop all support for "tenant".
|
||||||
if req_version.matches(None, "3.38") or not context.is_admin:
|
if req_version.matches(None,
|
||||||
|
mv.GROUP_REPLICATION) or not context.is_admin:
|
||||||
params.pop('project_id', None)
|
params.pop('project_id', None)
|
||||||
params.pop('tenant_id', None)
|
params.pop('tenant_id', None)
|
||||||
project_id = params.get(
|
project_id = params.get(
|
||||||
|
@ -17,6 +17,7 @@ from six.moves import http_client
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v3.views import messages as messages_view
|
from cinder.api.v3.views import messages as messages_view
|
||||||
from cinder.message import api as message_api
|
from cinder.message import api as message_api
|
||||||
@ -25,9 +26,6 @@ from cinder.message import message_field
|
|||||||
import cinder.policy
|
import cinder.policy
|
||||||
|
|
||||||
|
|
||||||
MESSAGES_BASE_MICRO_VERSION = '3.3'
|
|
||||||
|
|
||||||
|
|
||||||
def check_policy(context, action, target_obj=None):
|
def check_policy(context, action, target_obj=None):
|
||||||
target = {
|
target = {
|
||||||
'project_id': context.project_id,
|
'project_id': context.project_id,
|
||||||
@ -62,7 +60,7 @@ class MessagesController(wsgi.Controller):
|
|||||||
message_field.translate_action(message['action_id']),
|
message_field.translate_action(message['action_id']),
|
||||||
message_field.translate_detail(message['detail_id']))
|
message_field.translate_detail(message['detail_id']))
|
||||||
|
|
||||||
@wsgi.Controller.api_version(MESSAGES_BASE_MICRO_VERSION)
|
@wsgi.Controller.api_version(mv.MESSAGES)
|
||||||
def show(self, req, id):
|
def show(self, req, id):
|
||||||
"""Return the given message."""
|
"""Return the given message."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
@ -75,7 +73,7 @@ class MessagesController(wsgi.Controller):
|
|||||||
self._build_user_message(message)
|
self._build_user_message(message)
|
||||||
return self._view_builder.detail(req, message)
|
return self._view_builder.detail(req, message)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(MESSAGES_BASE_MICRO_VERSION)
|
@wsgi.Controller.api_version(mv.MESSAGES)
|
||||||
def delete(self, req, id):
|
def delete(self, req, id):
|
||||||
"""Delete a message."""
|
"""Delete a message."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
@ -87,7 +85,7 @@ class MessagesController(wsgi.Controller):
|
|||||||
|
|
||||||
return webob.Response(status_int=http_client.NO_CONTENT)
|
return webob.Response(status_int=http_client.NO_CONTENT)
|
||||||
|
|
||||||
@wsgi.Controller.api_version(MESSAGES_BASE_MICRO_VERSION)
|
@wsgi.Controller.api_version(mv.MESSAGES)
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
"""Returns a list of messages, transformed through view builder."""
|
"""Returns a list of messages, transformed through view builder."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
@ -100,14 +98,14 @@ class MessagesController(wsgi.Controller):
|
|||||||
sort_keys = None
|
sort_keys = None
|
||||||
sort_dirs = None
|
sort_dirs = None
|
||||||
|
|
||||||
if api_version.matches("3.5"):
|
if api_version.matches(mv.MESSAGES_PAGINATION):
|
||||||
filters = req.params.copy()
|
filters = req.params.copy()
|
||||||
marker, limit, offset = common.get_pagination_params(filters)
|
marker, limit, offset = common.get_pagination_params(filters)
|
||||||
sort_keys, sort_dirs = common.get_sort_params(filters)
|
sort_keys, sort_dirs = common.get_sort_params(filters)
|
||||||
|
|
||||||
if api_version.matches(common.FILTERING_VERSION):
|
if api_version.matches(mv.RESOURCE_FILTER):
|
||||||
support_like = (True if api_version.matches(
|
support_like = (True if api_version.matches(
|
||||||
common.LIKE_FILTER_VERSION) else False)
|
mv.LIKE_FILTER) else False)
|
||||||
common.reject_invalid_filters(context, filters, 'message',
|
common.reject_invalid_filters(context, filters, 'message',
|
||||||
support_like)
|
support_like)
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
@ -41,13 +42,14 @@ class ManageResource(object):
|
|||||||
raise exception.VersionNotFoundForAPIMethod(version=version)
|
raise exception.VersionNotFoundForAPIMethod(version=version)
|
||||||
|
|
||||||
def _get_resources(self, req, is_detail):
|
def _get_resources(self, req, is_detail):
|
||||||
self._ensure_min_version(req, '3.8')
|
self._ensure_min_version(req, mv.MANAGE_EXISTING_LIST)
|
||||||
|
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
self._authorizer(context)
|
self._authorizer(context)
|
||||||
|
|
||||||
params = req.params.copy()
|
params = req.params.copy()
|
||||||
cluster_name, host = common.get_cluster_host(req, params, '3.17')
|
cluster_name, host = common.get_cluster_host(
|
||||||
|
req, params, mv.MANAGE_EXISTING_CLUSTER)
|
||||||
marker, limit, offset = common.get_pagination_params(params)
|
marker, limit, offset = common.get_pagination_params(params)
|
||||||
sort_keys, sort_dirs = common.get_sort_params(params,
|
sort_keys, sort_dirs = common.get_sort_params(params,
|
||||||
default_key='reference')
|
default_key='reference')
|
||||||
|
@ -13,13 +13,11 @@
|
|||||||
"""The resource filters api."""
|
"""The resource filters api."""
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v3.views import resource_filters as filter_views
|
from cinder.api.v3.views import resource_filters as filter_views
|
||||||
|
|
||||||
|
|
||||||
FILTER_API_VERSION = '3.33'
|
|
||||||
|
|
||||||
|
|
||||||
class ResourceFiltersController(wsgi.Controller):
|
class ResourceFiltersController(wsgi.Controller):
|
||||||
"""The resource filter API controller for the OpenStack API."""
|
"""The resource filter API controller for the OpenStack API."""
|
||||||
|
|
||||||
@ -30,7 +28,7 @@ class ResourceFiltersController(wsgi.Controller):
|
|||||||
self.ext_mgr = ext_mgr
|
self.ext_mgr = ext_mgr
|
||||||
super(ResourceFiltersController, self).__init__()
|
super(ResourceFiltersController, self).__init__()
|
||||||
|
|
||||||
@wsgi.Controller.api_version(FILTER_API_VERSION)
|
@wsgi.Controller.api_version(mv.RESOURCE_FILTER_CONFIG)
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
"""Return a list of resource filters."""
|
"""Return a list of resource filters."""
|
||||||
resource = req.params.get('resource', None)
|
resource = req.params.get('resource', None)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
|
|
||||||
from cinder.api.contrib import snapshot_manage as snapshot_manage_v2
|
from cinder.api.contrib import snapshot_manage as snapshot_manage_v2
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v3 import resource_common_manage as common
|
from cinder.api.v3 import resource_common_manage as common
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ class SnapshotManageController(common.ManageResource,
|
|||||||
|
|
||||||
@wsgi.response(http_client.ACCEPTED)
|
@wsgi.response(http_client.ACCEPTED)
|
||||||
def create(self, req, body):
|
def create(self, req, body):
|
||||||
self._ensure_min_version(req, "3.8")
|
self._ensure_min_version(req, mv.MANAGE_EXISTING_LIST)
|
||||||
return super(SnapshotManageController, self).create(req, body)
|
return super(SnapshotManageController, self).create(req, body)
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import ast
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v2 import snapshots as snapshots_v2
|
from cinder.api.v2 import snapshots as snapshots_v2
|
||||||
from cinder.api.v3.views import snapshots as snapshot_views
|
from cinder.api.v3.views import snapshots as snapshot_views
|
||||||
@ -56,9 +57,10 @@ class SnapshotsController(snapshots_v2.SnapshotsController):
|
|||||||
req_version=None):
|
req_version=None):
|
||||||
"""Formats allowed filters"""
|
"""Formats allowed filters"""
|
||||||
|
|
||||||
# if the max version is less than or same as 3.21
|
# if the max version is less than SNAPSHOT_LIST_METADATA_FILTER
|
||||||
# metadata based filtering is not supported
|
# metadata based filtering is not supported
|
||||||
if req_version.matches(None, "3.21"):
|
if req_version.matches(
|
||||||
|
None, mv.get_prior_version(mv.SNAPSHOT_LIST_METADATA_FILTER)):
|
||||||
filters.pop('metadata', None)
|
filters.pop('metadata', None)
|
||||||
|
|
||||||
# Filter out invalid options
|
# Filter out invalid options
|
||||||
@ -84,7 +86,7 @@ class SnapshotsController(snapshots_v2.SnapshotsController):
|
|||||||
self._format_snapshot_filter_options(search_opts)
|
self._format_snapshot_filter_options(search_opts)
|
||||||
|
|
||||||
req_version = req.api_version_request
|
req_version = req.api_version_request
|
||||||
if req_version.matches("3.30", None) and 'name' in sort_keys:
|
if req_version.matches(mv.SNAPSHOT_SORT, None) and 'name' in sort_keys:
|
||||||
sort_keys[sort_keys.index('name')] = 'display_name'
|
sort_keys[sort_keys.index('name')] = 'display_name'
|
||||||
|
|
||||||
# NOTE(thingee): v3 API allows name instead of display_name
|
# NOTE(thingee): v3 API allows name instead of display_name
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder import utils
|
from cinder import utils
|
||||||
|
|
||||||
|
|
||||||
@ -60,20 +61,21 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
|
|
||||||
req_version = request.api_version_request
|
req_version = request.api_version_request
|
||||||
# Add group_snapshot_id and source_group_id if min version is greater
|
# Add group_snapshot_id and source_group_id if min version is greater
|
||||||
# than or equal to 3.14.
|
# than or equal to GROUP_SNAPSHOTS.
|
||||||
if req_version.matches("3.14", None):
|
if req_version.matches(mv.GROUP_SNAPSHOTS, None):
|
||||||
group_ref['group']['group_snapshot_id'] = group.group_snapshot_id
|
group_ref['group']['group_snapshot_id'] = group.group_snapshot_id
|
||||||
group_ref['group']['source_group_id'] = group.source_group_id
|
group_ref['group']['source_group_id'] = group.source_group_id
|
||||||
|
|
||||||
# Add volumes if min version is greater than or equal to 3.25.
|
# Add volumes if min version is greater than or equal to
|
||||||
if req_version.matches("3.25", None):
|
# GROUP_VOLUME_LIST.
|
||||||
|
if req_version.matches(mv.GROUP_VOLUME_LIST, None):
|
||||||
if utils.get_bool_param('list_volume', request.params):
|
if utils.get_bool_param('list_volume', request.params):
|
||||||
group_ref['group']['volumes'] = [volume.id
|
group_ref['group']['volumes'] = [volume.id
|
||||||
for volume in group.volumes]
|
for volume in group.volumes]
|
||||||
|
|
||||||
# Add replication_status if min version is greater than or equal
|
# Add replication_status if min version is greater than or equal
|
||||||
# to 3.38.
|
# to GROUP_REPLICATION.
|
||||||
if req_version.matches("3.38", None):
|
if req_version.matches(mv.GROUP_REPLICATION, None):
|
||||||
group_ref['group']['replication_status'] = group.replication_status
|
group_ref['group']['replication_status'] = group.replication_status
|
||||||
|
|
||||||
return group_ref
|
return group_ref
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.views import snapshots as views_v2
|
from cinder.api.views import snapshots as views_v2
|
||||||
|
|
||||||
|
|
||||||
@ -25,10 +26,10 @@ class ViewBuilder(views_v2.ViewBuilder):
|
|||||||
|
|
||||||
req_version = request.api_version_request
|
req_version = request.api_version_request
|
||||||
# Add group_snapshot_id if min version is greater than or equal
|
# Add group_snapshot_id if min version is greater than or equal
|
||||||
# to 3.14.
|
# to GROUP_SNAPSHOTS.
|
||||||
if req_version.matches("3.14", None):
|
if req_version.matches(mv.GROUP_SNAPSHOTS, None):
|
||||||
snapshot_ref['snapshot']['group_snapshot_id'] = (
|
snapshot_ref['snapshot']['group_snapshot_id'] = (
|
||||||
snapshot.get('group_snapshot_id'))
|
snapshot.get('group_snapshot_id'))
|
||||||
if req_version.matches("3.41", None):
|
if req_version.matches(mv.SNAPSHOT_LIST_USER_ID, None):
|
||||||
snapshot_ref['snapshot']['user_id'] = snapshot.get('user_id')
|
snapshot_ref['snapshot']['user_id'] = snapshot.get('user_id')
|
||||||
return snapshot_ref
|
return snapshot_ref
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v2.views import volumes as views_v2
|
from cinder.api.v2.views import volumes as views_v2
|
||||||
|
|
||||||
|
|
||||||
@ -41,14 +42,14 @@ class ViewBuilder(views_v2.ViewBuilder):
|
|||||||
volume_ref = super(ViewBuilder, self).detail(request, volume)
|
volume_ref = super(ViewBuilder, self).detail(request, volume)
|
||||||
|
|
||||||
req_version = request.api_version_request
|
req_version = request.api_version_request
|
||||||
# Add group_id if min version is greater than or equal to 3.13.
|
# Add group_id if min version is greater than or equal to GROUP_VOLUME.
|
||||||
if req_version.matches("3.13", None):
|
if req_version.matches(mv.GROUP_VOLUME, None):
|
||||||
volume_ref['volume']['group_id'] = volume.get('group_id')
|
volume_ref['volume']['group_id'] = volume.get('group_id')
|
||||||
|
|
||||||
# Add provider_id if min version is greater than or equal to 3.21
|
# Add provider_id if min version is greater than or equal to
|
||||||
# for admin.
|
# VOLUME_DETAIL_PROVIDER_ID for admin.
|
||||||
if (request.environ['cinder.context'].is_admin and
|
if (request.environ['cinder.context'].is_admin and
|
||||||
req_version.matches("3.21", None)):
|
req_version.matches(mv.VOLUME_DETAIL_PROVIDER_ID, None)):
|
||||||
volume_ref['volume']['provider_id'] = volume.get('provider_id')
|
volume_ref['volume']['provider_id'] = volume.get('provider_id')
|
||||||
|
|
||||||
return volume_ref
|
return volume_ref
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
|
|
||||||
from cinder.api.contrib import volume_manage as volume_manage_v2
|
from cinder.api.contrib import volume_manage as volume_manage_v2
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v3 import resource_common_manage as common
|
from cinder.api.v3 import resource_common_manage as common
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ class VolumeManageController(common.ManageResource,
|
|||||||
|
|
||||||
@wsgi.response(http_client.ACCEPTED)
|
@wsgi.response(http_client.ACCEPTED)
|
||||||
def create(self, req, body):
|
def create(self, req, body):
|
||||||
self._ensure_min_version(req, "3.8")
|
self._ensure_min_version(req, mv.MANAGE_EXISTING_LIST)
|
||||||
return super(VolumeManageController, self).create(req, body)
|
return super(VolumeManageController, self).create(req, body)
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,13 +22,11 @@ import six
|
|||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v2 import volume_metadata as volume_meta_v2
|
from cinder.api.v2 import volume_metadata as volume_meta_v2
|
||||||
|
|
||||||
|
|
||||||
METADATA_MICRO_VERSION = '3.15'
|
|
||||||
|
|
||||||
|
|
||||||
class Controller(volume_meta_v2.Controller):
|
class Controller(volume_meta_v2.Controller):
|
||||||
"""The volume metadata API controller for the OpenStack API."""
|
"""The volume metadata API controller for the OpenStack API."""
|
||||||
def _validate_etag(self, req, volume_id):
|
def _validate_etag(self, req, volume_id):
|
||||||
@ -46,7 +44,7 @@ class Controller(volume_meta_v2.Controller):
|
|||||||
def index(self, req, volume_id):
|
def index(self, req, volume_id):
|
||||||
req_version = req.api_version_request
|
req_version = req.api_version_request
|
||||||
metadata = super(Controller, self).index(req, volume_id)
|
metadata = super(Controller, self).index(req, volume_id)
|
||||||
if req_version.matches(METADATA_MICRO_VERSION):
|
if req_version.matches(mv.ETAGS):
|
||||||
data = jsonutils.dumps(metadata)
|
data = jsonutils.dumps(metadata)
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
data = data.encode('utf-8')
|
data = data.encode('utf-8')
|
||||||
@ -59,7 +57,7 @@ class Controller(volume_meta_v2.Controller):
|
|||||||
@wsgi.extends
|
@wsgi.extends
|
||||||
def update(self, req, volume_id, id, body):
|
def update(self, req, volume_id, id, body):
|
||||||
req_version = req.api_version_request
|
req_version = req.api_version_request
|
||||||
if req_version.matches(METADATA_MICRO_VERSION):
|
if req_version.matches(mv.ETAGS):
|
||||||
if not self._validate_etag(req, volume_id):
|
if not self._validate_etag(req, volume_id):
|
||||||
return webob.Response(
|
return webob.Response(
|
||||||
status_int=http_client.PRECONDITION_FAILED)
|
status_int=http_client.PRECONDITION_FAILED)
|
||||||
@ -69,7 +67,7 @@ class Controller(volume_meta_v2.Controller):
|
|||||||
@wsgi.extends
|
@wsgi.extends
|
||||||
def update_all(self, req, volume_id, body):
|
def update_all(self, req, volume_id, body):
|
||||||
req_version = req.api_version_request
|
req_version = req.api_version_request
|
||||||
if req_version.matches(METADATA_MICRO_VERSION):
|
if req_version.matches(mv.ETAGS):
|
||||||
if not self._validate_etag(req, volume_id):
|
if not self._validate_etag(req, volume_id):
|
||||||
return webob.Response(
|
return webob.Response(
|
||||||
status_int=http_client.PRECONDITION_FAILED)
|
status_int=http_client.PRECONDITION_FAILED)
|
||||||
|
@ -21,6 +21,7 @@ import webob
|
|||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v2 import volumes as volumes_v2
|
from cinder.api.v2 import volumes as volumes_v2
|
||||||
from cinder.api.v3.views import volumes as volume_views_v3
|
from cinder.api.v3.views import volumes as volume_views_v3
|
||||||
@ -33,8 +34,6 @@ from cinder import utils
|
|||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
SUMMARY_BASE_MICRO_VERSION = '3.12'
|
|
||||||
|
|
||||||
|
|
||||||
def check_policy(context, action, target_obj=None):
|
def check_policy(context, action, target_obj=None):
|
||||||
target = {
|
target = {
|
||||||
@ -65,7 +64,7 @@ class VolumeController(volumes_v2.VolumeController):
|
|||||||
force = False
|
force = False
|
||||||
|
|
||||||
params = ""
|
params = ""
|
||||||
if req_version.matches('3.23'):
|
if req_version.matches(mv.VOLUME_LIST_BOOTABLE):
|
||||||
force = utils.get_bool_param('force', req.params)
|
force = utils.get_bool_param('force', req.params)
|
||||||
if cascade or force:
|
if cascade or force:
|
||||||
params = "(cascade: %(c)s, force: %(f)s)" % {'c': cascade,
|
params = "(cascade: %(c)s, force: %(f)s)" % {'c': cascade,
|
||||||
@ -88,10 +87,10 @@ class VolumeController(volumes_v2.VolumeController):
|
|||||||
@common.process_general_filtering('volume')
|
@common.process_general_filtering('volume')
|
||||||
def _process_volume_filtering(self, context=None, filters=None,
|
def _process_volume_filtering(self, context=None, filters=None,
|
||||||
req_version=None):
|
req_version=None):
|
||||||
if req_version.matches(None, "3.3"):
|
if req_version.matches(None, mv.MESSAGES):
|
||||||
filters.pop('glance_metadata', None)
|
filters.pop('glance_metadata', None)
|
||||||
|
|
||||||
if req_version.matches(None, "3.9"):
|
if req_version.matches(None, mv.BACKUP_UPDATE):
|
||||||
filters.pop('group_id', None)
|
filters.pop('group_id', None)
|
||||||
|
|
||||||
utils.remove_invalid_filter_options(
|
utils.remove_invalid_filter_options(
|
||||||
@ -119,7 +118,8 @@ class VolumeController(volumes_v2.VolumeController):
|
|||||||
if 'name' in filters:
|
if 'name' in filters:
|
||||||
filters['display_name'] = filters.pop('name')
|
filters['display_name'] = filters.pop('name')
|
||||||
|
|
||||||
strict = req.api_version_request.matches("3.2", None)
|
strict = req.api_version_request.matches(
|
||||||
|
mv.VOLUME_LIST_BOOTABLE, None)
|
||||||
self.volume_api.check_volume_filters(filters, strict)
|
self.volume_api.check_volume_filters(filters, strict)
|
||||||
|
|
||||||
volumes = self.volume_api.get_all(context, marker, limit,
|
volumes = self.volume_api.get_all(context, marker, limit,
|
||||||
@ -140,7 +140,7 @@ class VolumeController(volumes_v2.VolumeController):
|
|||||||
volumes = self._view_builder.summary_list(req, volumes)
|
volumes = self._view_builder.summary_list(req, volumes)
|
||||||
return volumes
|
return volumes
|
||||||
|
|
||||||
@wsgi.Controller.api_version(SUMMARY_BASE_MICRO_VERSION)
|
@wsgi.Controller.api_version(mv.VOLUME_SUMMARY)
|
||||||
def summary(self, req):
|
def summary(self, req):
|
||||||
"""Return summary of volumes."""
|
"""Return summary of volumes."""
|
||||||
view_builder_v3 = volume_views_v3.ViewBuilder()
|
view_builder_v3 = volume_views_v3.ViewBuilder()
|
||||||
@ -154,7 +154,7 @@ class VolumeController(volumes_v2.VolumeController):
|
|||||||
context, filters=filters)
|
context, filters=filters)
|
||||||
|
|
||||||
req_version = req.api_version_request
|
req_version = req.api_version_request
|
||||||
if req_version.matches("3.36"):
|
if req_version.matches(mv.VOLUME_SUMMARY_METADATA):
|
||||||
all_distinct_metadata = metadata
|
all_distinct_metadata = metadata
|
||||||
else:
|
else:
|
||||||
all_distinct_metadata = None
|
all_distinct_metadata = None
|
||||||
@ -163,7 +163,7 @@ class VolumeController(volumes_v2.VolumeController):
|
|||||||
all_distinct_metadata)
|
all_distinct_metadata)
|
||||||
|
|
||||||
@wsgi.response(http_client.ACCEPTED)
|
@wsgi.response(http_client.ACCEPTED)
|
||||||
@wsgi.Controller.api_version('3.40')
|
@wsgi.Controller.api_version(mv.VOLUME_REVERT)
|
||||||
@wsgi.action('revert')
|
@wsgi.action('revert')
|
||||||
def revert(self, req, id, body):
|
def revert(self, req, id, body):
|
||||||
"""revert a volume to a snapshot"""
|
"""revert a volume to a snapshot"""
|
||||||
@ -208,8 +208,8 @@ class VolumeController(volumes_v2.VolumeController):
|
|||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
|
|
||||||
req_version = req.api_version_request
|
req_version = req.api_version_request
|
||||||
# Remove group_id from body if max version is less than 3.13.
|
# Remove group_id from body if max version is less than GROUP_VOLUME.
|
||||||
if req_version.matches(None, "3.12"):
|
if req_version.matches(None, mv.get_prior_version(mv.GROUP_VOLUME)):
|
||||||
# NOTE(xyang): The group_id is from a group created with a
|
# NOTE(xyang): The group_id is from a group created with a
|
||||||
# group_type. So with this group_id, we've got a group_type
|
# group_type. So with this group_id, we've got a group_type
|
||||||
# for this volume. Also if group_id is passed in, that means
|
# for this volume. Also if group_id is passed in, that means
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.v3.views import workers as workers_view
|
from cinder.api.v3.views import workers as workers_view
|
||||||
from cinder import db
|
from cinder import db
|
||||||
@ -98,7 +99,7 @@ class WorkerController(wsgi.Controller):
|
|||||||
|
|
||||||
return params
|
return params
|
||||||
|
|
||||||
@wsgi.Controller.api_version('3.24')
|
@wsgi.Controller.api_version(mv.WORKERS_CLEANUP)
|
||||||
@wsgi.response(202)
|
@wsgi.response(202)
|
||||||
def cleanup(self, req, body=None):
|
def cleanup(self, req, body=None):
|
||||||
"""Do the cleanup on resources from a specific service/host/node."""
|
"""Do the cleanup on resources from a specific service/host/node."""
|
||||||
|
@ -51,7 +51,7 @@ _KNOWN_VERSIONS = {
|
|||||||
"status": "CURRENT",
|
"status": "CURRENT",
|
||||||
"version": api_version_request._MAX_API_VERSION,
|
"version": api_version_request._MAX_API_VERSION,
|
||||||
"min_version": api_version_request._MIN_API_VERSION,
|
"min_version": api_version_request._MIN_API_VERSION,
|
||||||
"updated": "2016-02-08T12:20:21Z",
|
"updated": api_version_request.UPDATED,
|
||||||
"links": _LINKS,
|
"links": _LINKS,
|
||||||
"media-types": [{
|
"media-types": [{
|
||||||
"base": "application/json",
|
"base": "application/json",
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from cinder.api import common
|
from cinder.api import common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
|
|
||||||
|
|
||||||
class ViewBuilder(common.ViewBuilder):
|
class ViewBuilder(common.ViewBuilder):
|
||||||
@ -78,7 +79,7 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
req_version = request.api_version_request
|
req_version = request.api_version_request
|
||||||
if req_version.matches("3.43"):
|
if req_version.matches(mv.BACKUP_METADATA):
|
||||||
backup_dict['backup']['metadata'] = backup.metadata
|
backup_dict['backup']['metadata'] = backup.metadata
|
||||||
return backup_dict
|
return backup_dict
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ CONF = config.CONF
|
|||||||
|
|
||||||
|
|
||||||
class VolumeRevertTests(volume_base.BaseVolumeTest):
|
class VolumeRevertTests(volume_base.BaseVolumeTest):
|
||||||
min_microversion = '3.40'
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup_clients(cls):
|
def setup_clients(cls):
|
||||||
|
@ -23,7 +23,7 @@ import webob
|
|||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from cinder.api.contrib import admin_actions
|
from cinder.api.contrib import admin_actions
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api import microversions as mv
|
||||||
from cinder.backup import api as backup_api
|
from cinder.backup import api as backup_api
|
||||||
from cinder.backup import rpcapi as backup_rpcapi
|
from cinder.backup import rpcapi as backup_rpcapi
|
||||||
from cinder.common import constants
|
from cinder.common import constants
|
||||||
@ -525,18 +525,16 @@ class AdminActionsTest(BaseAdminTest):
|
|||||||
force_host_copy=False, version=None,
|
force_host_copy=False, version=None,
|
||||||
cluster=None):
|
cluster=None):
|
||||||
# build request to migrate to host
|
# build request to migrate to host
|
||||||
# req = fakes.HTTPRequest.blank('/v3/%s/volumes/%s/action' % (
|
|
||||||
# fake.PROJECT_ID, volume['id']))
|
|
||||||
req = webob.Request.blank('/v3/%s/volumes/%s/action' % (
|
req = webob.Request.blank('/v3/%s/volumes/%s/action' % (
|
||||||
fake.PROJECT_ID, volume['id']))
|
fake.PROJECT_ID, volume['id']))
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.headers['content-type'] = 'application/json'
|
req.headers['content-type'] = 'application/json'
|
||||||
body = {'os-migrate_volume': {'host': host,
|
body = {'os-migrate_volume': {'host': host,
|
||||||
'force_host_copy': force_host_copy}}
|
'force_host_copy': force_host_copy}}
|
||||||
version = version or '3.0'
|
version = version or mv.BASE_VERSION
|
||||||
req.headers = {'OpenStack-API-Version': 'volume %s' % version}
|
req.headers = mv.get_mv_header(version)
|
||||||
req.api_version_request = api_version.APIVersionRequest(version)
|
req.api_version_request = mv.get_api_version(version)
|
||||||
if version == '3.16':
|
if version == mv.VOLUME_MIGRATE_CLUSTER:
|
||||||
body['os-migrate_volume']['cluster'] = cluster
|
body['os-migrate_volume']['cluster'] = cluster
|
||||||
req.body = jsonutils.dump_as_bytes(body)
|
req.body = jsonutils.dump_as_bytes(body)
|
||||||
req.environ['cinder.context'] = ctx
|
req.environ['cinder.context'] = ctx
|
||||||
@ -547,7 +545,9 @@ class AdminActionsTest(BaseAdminTest):
|
|||||||
volume = db.volume_get(self.ctx, volume['id'])
|
volume = db.volume_get(self.ctx, volume['id'])
|
||||||
return volume
|
return volume
|
||||||
|
|
||||||
@ddt.data('3.0', '3.15', '3.16')
|
@ddt.data(mv.BASE_VERSION,
|
||||||
|
mv.get_prior_version(mv.VOLUME_MIGRATE_CLUSTER),
|
||||||
|
mv.VOLUME_MIGRATE_CLUSTER)
|
||||||
def test_migrate_volume_success_3(self, version):
|
def test_migrate_volume_success_3(self, version):
|
||||||
expected_status = http_client.ACCEPTED
|
expected_status = http_client.ACCEPTED
|
||||||
host = 'test2'
|
host = 'test2'
|
||||||
@ -563,7 +563,8 @@ class AdminActionsTest(BaseAdminTest):
|
|||||||
cluster = 'cluster'
|
cluster = 'cluster'
|
||||||
volume = self._migrate_volume_prep()
|
volume = self._migrate_volume_prep()
|
||||||
volume = self._migrate_volume_3_exec(self.ctx, volume, host,
|
volume = self._migrate_volume_3_exec(self.ctx, volume, host,
|
||||||
expected_status, version='3.16',
|
expected_status,
|
||||||
|
version=mv.VOLUME_MIGRATE_CLUSTER,
|
||||||
cluster=cluster)
|
cluster=cluster)
|
||||||
self.assertEqual('starting', volume['migration_status'])
|
self.assertEqual('starting', volume['migration_status'])
|
||||||
|
|
||||||
@ -574,7 +575,8 @@ class AdminActionsTest(BaseAdminTest):
|
|||||||
volume = self._migrate_volume_prep()
|
volume = self._migrate_volume_prep()
|
||||||
self.assertRaises(exception.InvalidInput,
|
self.assertRaises(exception.InvalidInput,
|
||||||
self._migrate_volume_3_exec, self.ctx, volume, host,
|
self._migrate_volume_3_exec, self.ctx, volume, host,
|
||||||
None, version='3.16', cluster=cluster)
|
None, version=mv.VOLUME_MIGRATE_CLUSTER,
|
||||||
|
cluster=cluster)
|
||||||
|
|
||||||
def _migrate_volume_exec(self, ctx, volume, host, expected_status,
|
def _migrate_volume_exec(self, ctx, volume, host, expected_status,
|
||||||
force_host_copy=False):
|
force_host_copy=False):
|
||||||
|
@ -17,7 +17,7 @@ import ddt
|
|||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import router as router_v3
|
from cinder.api.v3 import router as router_v3
|
||||||
from cinder.backup import api as backup_api
|
from cinder.backup import api as backup_api
|
||||||
from cinder import context
|
from cinder import context
|
||||||
@ -57,7 +57,8 @@ class BackupProjectAttributeTest(test.TestCase):
|
|||||||
self.stubs.Set(backup_api.API, 'get', fake_backup_get)
|
self.stubs.Set(backup_api.API, 'get', fake_backup_get)
|
||||||
self.stubs.Set(backup_api.API, 'get_all', fake_backup_get_all)
|
self.stubs.Set(backup_api.API, 'get_all', fake_backup_get_all)
|
||||||
|
|
||||||
def _send_backup_request(self, ctx, detail=False, version='3.18'):
|
def _send_backup_request(self, ctx, detail=False,
|
||||||
|
version=mv.BACKUP_PROJECT):
|
||||||
req = None
|
req = None
|
||||||
if detail:
|
if detail:
|
||||||
req = webob.Request.blank(('/v3/%s/backups/detail'
|
req = webob.Request.blank(('/v3/%s/backups/detail'
|
||||||
@ -67,8 +68,8 @@ class BackupProjectAttributeTest(test.TestCase):
|
|||||||
fake.BACKUP_ID))
|
fake.BACKUP_ID))
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.environ['cinder.context'] = ctx
|
req.environ['cinder.context'] = ctx
|
||||||
req.headers['OpenStack-API-Version'] = 'volume ' + version
|
req.headers = mv.get_mv_header(version)
|
||||||
req.api_version_request = api_version.APIVersionRequest(version)
|
req.api_version_request = mv.get_api_version(version)
|
||||||
res = req.get_response(app())
|
res = req.get_response(app())
|
||||||
|
|
||||||
if detail:
|
if detail:
|
||||||
@ -97,5 +98,6 @@ class BackupProjectAttributeTest(test.TestCase):
|
|||||||
|
|
||||||
def test_get_backup_under_allowed_api_version(self):
|
def test_get_backup_under_allowed_api_version(self):
|
||||||
ctx = context.RequestContext(fake.USER2_ID, fake.PROJECT_ID, True)
|
ctx = context.RequestContext(fake.USER2_ID, fake.PROJECT_ID, True)
|
||||||
bak = self._send_backup_request(ctx, version='3.17')
|
bak = self._send_backup_request(
|
||||||
|
ctx, version=mv.get_prior_version(mv.BACKUP_PROJECT))
|
||||||
self.assertNotIn('os-backup-project-attr:project_id', bak)
|
self.assertNotIn('os-backup-project-attr:project_id', bak)
|
||||||
|
@ -25,6 +25,7 @@ from six.moves import http_client
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api.contrib import backups
|
from cinder.api.contrib import backups
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api.openstack import api_version_request as api_version
|
||||||
# needed for stubs to work
|
# needed for stubs to work
|
||||||
import cinder.backup
|
import cinder.backup
|
||||||
@ -117,8 +118,8 @@ class BackupsAPITestCase(test.TestCase):
|
|||||||
req = webob.Request.blank('/v3/%s/backups/%s' % (
|
req = webob.Request.blank('/v3/%s/backups/%s' % (
|
||||||
fake.PROJECT_ID, backup.id))
|
fake.PROJECT_ID, backup.id))
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
|
req.headers = mv.get_mv_header(mv.BACKUP_METADATA)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume 3.43'
|
|
||||||
res = req.get_response(fakes.wsgi_app(
|
res = req.get_response(fakes.wsgi_app(
|
||||||
fake_auth_context=self.user_context))
|
fake_auth_context=self.user_context))
|
||||||
res_dict = jsonutils.loads(res.body)
|
res_dict = jsonutils.loads(res.body)
|
||||||
@ -131,6 +132,7 @@ class BackupsAPITestCase(test.TestCase):
|
|||||||
req = webob.Request.blank('/v2/%s/backups/%s' % (
|
req = webob.Request.blank('/v2/%s/backups/%s' % (
|
||||||
fake.PROJECT_ID, fake.WILL_NOT_BE_FOUND_ID))
|
fake.PROJECT_ID, fake.WILL_NOT_BE_FOUND_ID))
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
|
req.headers = mv.get_mv_header(mv.BACKUP_METADATA)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
res = req.get_response(fakes.wsgi_app(
|
res = req.get_response(fakes.wsgi_app(
|
||||||
fake_auth_context=self.user_context))
|
fake_auth_context=self.user_context))
|
||||||
@ -330,9 +332,9 @@ class BackupsAPITestCase(test.TestCase):
|
|||||||
|
|
||||||
req = webob.Request.blank('/v3/%s/backups/detail' % fake.PROJECT_ID)
|
req = webob.Request.blank('/v3/%s/backups/detail' % fake.PROJECT_ID)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
|
req.headers = mv.get_mv_header(mv.BACKUP_METADATA)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['Accept'] = 'application/json'
|
req.headers['Accept'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume 3.43'
|
|
||||||
res = req.get_response(fakes.wsgi_app(
|
res = req.get_response(fakes.wsgi_app(
|
||||||
fake_auth_context=self.user_context))
|
fake_auth_context=self.user_context))
|
||||||
res_dict = jsonutils.loads(res.body)
|
res_dict = jsonutils.loads(res.body)
|
||||||
@ -536,8 +538,8 @@ class BackupsAPITestCase(test.TestCase):
|
|||||||
}
|
}
|
||||||
req = webob.Request.blank('/v3/%s/backups' % fake.PROJECT_ID)
|
req = webob.Request.blank('/v3/%s/backups' % fake.PROJECT_ID)
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
|
req.headers = mv.get_mv_header(mv.BACKUP_METADATA)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume 3.43'
|
|
||||||
req.body = jsonutils.dump_as_bytes(body)
|
req.body = jsonutils.dump_as_bytes(body)
|
||||||
res = req.get_response(fakes.wsgi_app(
|
res = req.get_response(fakes.wsgi_app(
|
||||||
fake_auth_context=self.user_context))
|
fake_auth_context=self.user_context))
|
||||||
@ -546,8 +548,8 @@ class BackupsAPITestCase(test.TestCase):
|
|||||||
req = webob.Request.blank('/v3/%s/backups/%s' % (
|
req = webob.Request.blank('/v3/%s/backups/%s' % (
|
||||||
fake.PROJECT_ID, res_dict['backup']['id']))
|
fake.PROJECT_ID, res_dict['backup']['id']))
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
|
req.headers = mv.get_mv_header(mv.BACKUP_METADATA)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume 3.43'
|
|
||||||
res = req.get_response(fakes.wsgi_app(
|
res = req.get_response(fakes.wsgi_app(
|
||||||
fake_auth_context=self.user_context))
|
fake_auth_context=self.user_context))
|
||||||
res_dict = jsonutils.loads(res.body)
|
res_dict = jsonutils.loads(res.body)
|
||||||
|
@ -19,6 +19,7 @@ import mock
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api.contrib import scheduler_stats
|
from cinder.api.contrib import scheduler_stats
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api.openstack import api_version_request as api_version
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -84,7 +85,7 @@ class SchedulerStatsAPITest(test.TestCase):
|
|||||||
fake.PROJECT_ID)
|
fake.PROJECT_ID)
|
||||||
mock_rpcapi.return_value = [dict(name='pool1',
|
mock_rpcapi.return_value = [dict(name='pool1',
|
||||||
capabilities=dict(foo='bar'))]
|
capabilities=dict(foo='bar'))]
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.28')
|
req.api_version_request = mv.get_api_version(mv.POOL_FILTER)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res = self.controller.get_pools(req)
|
res = self.controller.get_pools(req)
|
||||||
|
|
||||||
@ -106,7 +107,7 @@ class SchedulerStatsAPITest(test.TestCase):
|
|||||||
'&foo=bar' % fake.PROJECT_ID)
|
'&foo=bar' % fake.PROJECT_ID)
|
||||||
mock_rpcapi.return_value = [dict(name='pool1',
|
mock_rpcapi.return_value = [dict(name='pool1',
|
||||||
capabilities=dict(foo='bar'))]
|
capabilities=dict(foo='bar'))]
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.28')
|
req.api_version_request = mv.get_api_version(mv.POOL_FILTER)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res = self.controller.get_pools(req)
|
res = self.controller.get_pools(req)
|
||||||
|
|
||||||
@ -175,8 +176,8 @@ class SchedulerStatsAPITest(test.TestCase):
|
|||||||
self.controller.get_pools,
|
self.controller.get_pools,
|
||||||
req)
|
req)
|
||||||
|
|
||||||
@ddt.data(('3.34', False),
|
@ddt.data((mv.get_prior_version(mv.POOL_TYPE_FILTER), False),
|
||||||
('3.35', True))
|
(mv.POOL_TYPE_FILTER, True))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
@mock.patch('cinder.scheduler.rpcapi.SchedulerAPI.get_pools')
|
@mock.patch('cinder.scheduler.rpcapi.SchedulerAPI.get_pools')
|
||||||
@mock.patch('cinder.api.common.reject_invalid_filters')
|
@mock.patch('cinder.api.common.reject_invalid_filters')
|
||||||
|
@ -25,7 +25,7 @@ import webob.exc
|
|||||||
|
|
||||||
from cinder.api.contrib import services
|
from cinder.api.contrib import services
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api import microversions as mv
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder import objects
|
from cinder import objects
|
||||||
@ -114,10 +114,10 @@ fake_services_list = [
|
|||||||
class FakeRequest(object):
|
class FakeRequest(object):
|
||||||
environ = {"cinder.context": context.get_admin_context()}
|
environ = {"cinder.context": context.get_admin_context()}
|
||||||
|
|
||||||
def __init__(self, version='3.0', **kwargs):
|
def __init__(self, version=mv.BASE_VERSION, **kwargs):
|
||||||
self.GET = kwargs
|
self.GET = kwargs
|
||||||
self.headers = {'OpenStack-API-Version': 'volume ' + version}
|
self.headers = mv.get_mv_header(version)
|
||||||
self.api_version_request = api_version.APIVersionRequest(version)
|
self.api_version_request = mv.get_api_version(version)
|
||||||
|
|
||||||
|
|
||||||
class FakeRequestWithBinary(FakeRequest):
|
class FakeRequestWithBinary(FakeRequest):
|
||||||
@ -246,19 +246,19 @@ class ServicesTest(test.TestCase):
|
|||||||
self.assertEqual(response, res_dict)
|
self.assertEqual(response, res_dict)
|
||||||
|
|
||||||
def test_failover_old_version(self):
|
def test_failover_old_version(self):
|
||||||
req = FakeRequest(version='3.18')
|
req = FakeRequest(version=mv.BACKUP_PROJECT)
|
||||||
self.assertRaises(exception.InvalidInput, self.controller.update, req,
|
self.assertRaises(exception.InvalidInput, self.controller.update, req,
|
||||||
'failover', {'cluster': 'cluster1'})
|
'failover', {'cluster': 'cluster1'})
|
||||||
|
|
||||||
def test_failover_no_values(self):
|
def test_failover_no_values(self):
|
||||||
req = FakeRequest(version='3.26')
|
req = FakeRequest(version=mv.REPLICATION_CLUSTER)
|
||||||
self.assertRaises(exception.InvalidInput, self.controller.update, req,
|
self.assertRaises(exception.InvalidInput, self.controller.update, req,
|
||||||
'failover', {'backend_id': 'replica1'})
|
'failover', {'backend_id': 'replica1'})
|
||||||
|
|
||||||
@ddt.data({'host': 'hostname'}, {'cluster': 'mycluster'})
|
@ddt.data({'host': 'hostname'}, {'cluster': 'mycluster'})
|
||||||
@mock.patch('cinder.volume.api.API.failover')
|
@mock.patch('cinder.volume.api.API.failover')
|
||||||
def test_failover(self, body, failover_mock):
|
def test_failover(self, body, failover_mock):
|
||||||
req = FakeRequest(version='3.26')
|
req = FakeRequest(version=mv.REPLICATION_CLUSTER)
|
||||||
body['backend_id'] = 'replica1'
|
body['backend_id'] = 'replica1'
|
||||||
res = self.controller.update(req, 'failover', body)
|
res = self.controller.update(req, 'failover', body)
|
||||||
self.assertEqual(202, res.status_code)
|
self.assertEqual(202, res.status_code)
|
||||||
@ -269,14 +269,14 @@ class ServicesTest(test.TestCase):
|
|||||||
@ddt.data({}, {'host': 'hostname', 'cluster': 'mycluster'})
|
@ddt.data({}, {'host': 'hostname', 'cluster': 'mycluster'})
|
||||||
@mock.patch('cinder.volume.api.API.failover')
|
@mock.patch('cinder.volume.api.API.failover')
|
||||||
def test_failover_invalid_input(self, body, failover_mock):
|
def test_failover_invalid_input(self, body, failover_mock):
|
||||||
req = FakeRequest(version='3.26')
|
req = FakeRequest(version=mv.REPLICATION_CLUSTER)
|
||||||
body['backend_id'] = 'replica1'
|
body['backend_id'] = 'replica1'
|
||||||
self.assertRaises(exception.InvalidInput,
|
self.assertRaises(exception.InvalidInput,
|
||||||
self.controller.update, req, 'failover', body)
|
self.controller.update, req, 'failover', body)
|
||||||
failover_mock.assert_not_called()
|
failover_mock.assert_not_called()
|
||||||
|
|
||||||
def test_services_list_with_cluster_name(self):
|
def test_services_list_with_cluster_name(self):
|
||||||
req = FakeRequest(version='3.7')
|
req = FakeRequest(version=mv.CLUSTER_SUPPORT)
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
|
|
||||||
response = {'services': [{'binary': 'cinder-scheduler',
|
response = {'services': [{'binary': 'cinder-scheduler',
|
||||||
@ -689,7 +689,7 @@ class ServicesTest(test.TestCase):
|
|||||||
def test_services_action_cluster_not_found(self, method, body,
|
def test_services_action_cluster_not_found(self, method, body,
|
||||||
mock_get_all_services):
|
mock_get_all_services):
|
||||||
url = '/v3/%s/os-services/%s' % (fake.PROJECT_ID, method)
|
url = '/v3/%s/os-services/%s' % (fake.PROJECT_ID, method)
|
||||||
req = fakes.HTTPRequest.blank(url, version='3.26')
|
req = fakes.HTTPRequest.blank(url, version=mv.REPLICATION_CLUSTER)
|
||||||
mock_get_all_services.return_value = []
|
mock_get_all_services.return_value = []
|
||||||
msg = 'No service found with cluster=%s' % mock.sentinel.cluster
|
msg = 'No service found with cluster=%s' % mock.sentinel.cluster
|
||||||
result = self.assertRaises(exception.InvalidInput,
|
result = self.assertRaises(exception.InvalidInput,
|
||||||
@ -729,7 +729,7 @@ class ServicesTest(test.TestCase):
|
|||||||
@mock.patch('cinder.api.contrib.services.ServiceController._set_log')
|
@mock.patch('cinder.api.contrib.services.ServiceController._set_log')
|
||||||
def test_set_log(self, set_log_mock):
|
def test_set_log(self, set_log_mock):
|
||||||
set_log_mock.return_value = None
|
set_log_mock.return_value = None
|
||||||
req = FakeRequest(version='3.32')
|
req = FakeRequest(version=mv.LOG_LEVEL)
|
||||||
body = mock.sentinel.body
|
body = mock.sentinel.body
|
||||||
res = self.controller.update(req, 'set-log', body)
|
res = self.controller.update(req, 'set-log', body)
|
||||||
self.assertEqual(set_log_mock.return_value, res)
|
self.assertEqual(set_log_mock.return_value, res)
|
||||||
@ -738,7 +738,7 @@ class ServicesTest(test.TestCase):
|
|||||||
@mock.patch('cinder.api.contrib.services.ServiceController._get_log')
|
@mock.patch('cinder.api.contrib.services.ServiceController._get_log')
|
||||||
def test_get_log(self, get_log_mock):
|
def test_get_log(self, get_log_mock):
|
||||||
get_log_mock.return_value = None
|
get_log_mock.return_value = None
|
||||||
req = FakeRequest(version='3.32')
|
req = FakeRequest(version=mv.LOG_LEVEL)
|
||||||
body = mock.sentinel.body
|
body = mock.sentinel.body
|
||||||
res = self.controller.update(req, 'get-log', body)
|
res = self.controller.update(req, 'get-log', body)
|
||||||
self.assertEqual(get_log_mock.return_value, res)
|
self.assertEqual(get_log_mock.return_value, res)
|
||||||
|
@ -17,6 +17,7 @@ import ddt
|
|||||||
import mock
|
import mock
|
||||||
|
|
||||||
from cinder.api.contrib import used_limits
|
from cinder.api.contrib import used_limits
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import api_version_request
|
from cinder.api.openstack import api_version_request
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -40,8 +41,11 @@ class UsedLimitsTestCase(test.TestCase):
|
|||||||
super(UsedLimitsTestCase, self).setUp()
|
super(UsedLimitsTestCase, self).setUp()
|
||||||
self.controller = used_limits.UsedLimitsController()
|
self.controller = used_limits.UsedLimitsController()
|
||||||
|
|
||||||
@ddt.data(('2.0', False), ('3.38', True), ('3.38', False), ('3.39', True),
|
@ddt.data(('2.0', False),
|
||||||
('3.39', False))
|
(mv.get_prior_version(mv.LIMITS_ADMIN_FILTER), True),
|
||||||
|
(mv.get_prior_version(mv.LIMITS_ADMIN_FILTER), False),
|
||||||
|
(mv.LIMITS_ADMIN_FILTER, True),
|
||||||
|
(mv.LIMITS_ADMIN_FILTER, False))
|
||||||
@mock.patch('cinder.quota.QUOTAS.get_project_quotas')
|
@mock.patch('cinder.quota.QUOTAS.get_project_quotas')
|
||||||
@mock.patch('cinder.policy.enforce')
|
@mock.patch('cinder.policy.enforce')
|
||||||
def test_used_limits(self, ver_project, _mock_policy_enforce,
|
def test_used_limits(self, ver_project, _mock_policy_enforce,
|
||||||
@ -78,9 +82,9 @@ class UsedLimitsTestCase(test.TestCase):
|
|||||||
self.controller.index(fake_req, res)
|
self.controller.index(fake_req, res)
|
||||||
abs_limits = res.obj['limits']['absolute']
|
abs_limits = res.obj['limits']['absolute']
|
||||||
|
|
||||||
# if admin, only 3.39 and req contains project_id filter, cinder
|
# if admin, only LIMITS_ADMIN_FILTER and req contains project_id
|
||||||
# returns the specified project's quota.
|
# filter, cinder returns the specified project's quota.
|
||||||
if version == '3.39' and has_project:
|
if version == mv.LIMITS_ADMIN_FILTER and has_project:
|
||||||
self.assertEqual(1, abs_limits['totalGigabytesUsed'])
|
self.assertEqual(1, abs_limits['totalGigabytesUsed'])
|
||||||
else:
|
else:
|
||||||
self.assertEqual(2, abs_limits['totalGigabytesUsed'])
|
self.assertEqual(2, abs_limits['totalGigabytesUsed'])
|
||||||
|
@ -24,7 +24,7 @@ from six.moves import http_client
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api.contrib import volume_actions
|
from cinder.api.contrib import volume_actions
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api import microversions as mv
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import db
|
from cinder import db
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -818,7 +818,7 @@ class VolumeImageActionsTest(test.TestCase):
|
|||||||
'size': 0}
|
'size': 0}
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def fake_image_service_create_3_1(self, *args):
|
def fake_image_service_create_with_params(self, *args):
|
||||||
ret = {
|
ret = {
|
||||||
'status': u'queued',
|
'status': u'queued',
|
||||||
'name': u'image_name',
|
'name': u'image_name',
|
||||||
@ -1017,13 +1017,13 @@ class VolumeImageActionsTest(test.TestCase):
|
|||||||
id,
|
id,
|
||||||
body)
|
body)
|
||||||
|
|
||||||
@ddt.data({'version': '3.41',
|
@ddt.data({'version': mv.get_prior_version(mv.VOLUME_EXTEND_INUSE),
|
||||||
'status': 'available'},
|
'status': 'available'},
|
||||||
{'version': '3.41',
|
{'version': mv.get_prior_version(mv.VOLUME_EXTEND_INUSE),
|
||||||
'status': 'in-use'},
|
'status': 'in-use'},
|
||||||
{'version': '3.42',
|
{'version': mv.VOLUME_EXTEND_INUSE,
|
||||||
'status': 'available'},
|
'status': 'available'},
|
||||||
{'version': '3.42',
|
{'version': mv.VOLUME_EXTEND_INUSE,
|
||||||
'status': 'in-use'})
|
'status': 'in-use'})
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_extend_attached_volume(self, version, status):
|
def test_extend_attached_volume(self, version, status):
|
||||||
@ -1035,9 +1035,9 @@ class VolumeImageActionsTest(test.TestCase):
|
|||||||
body = {"os-extend": {"new_size": 2}}
|
body = {"os-extend": {"new_size": 2}}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/volumes/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/volumes/%s/action' %
|
||||||
(fake.PROJECT_ID, vol['id']))
|
(fake.PROJECT_ID, vol['id']))
|
||||||
req.api_version_request = api_version.APIVersionRequest(version)
|
req.api_version_request = mv.get_api_version(version)
|
||||||
self.controller._extend(req, vol['id'], body)
|
self.controller._extend(req, vol['id'], body)
|
||||||
if version == '3.42' and status == 'in-use':
|
if version == mv.VOLUME_EXTEND_INUSE and status == 'in-use':
|
||||||
mock_extend.assert_called_with(req.environ['cinder.context'],
|
mock_extend.assert_called_with(req.environ['cinder.context'],
|
||||||
vol, 2, attached=True)
|
vol, 2, attached=True)
|
||||||
else:
|
else:
|
||||||
@ -1117,8 +1117,8 @@ class VolumeImageActionsTest(test.TestCase):
|
|||||||
id = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
|
id = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
|
||||||
req = fakes.HTTPRequest.blank('/v3/tenant1/volumes/%s/action' % id)
|
req = fakes.HTTPRequest.blank('/v3/tenant1/volumes/%s/action' % id)
|
||||||
req.environ['cinder.context'].is_admin = False
|
req.environ['cinder.context'].is_admin = False
|
||||||
req.headers = {'OpenStack-API-Version': 'volume 3.1'}
|
req.headers = mv.get_mv_header(mv.UPLOAD_IMAGE_PARAMS)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.1')
|
req.api_version_request = mv.get_api_version(mv.UPLOAD_IMAGE_PARAMS)
|
||||||
body = self._get_os_volume_upload_image()
|
body = self._get_os_volume_upload_image()
|
||||||
body['os-volume_upload_image']['visibility'] = 'public'
|
body['os-volume_upload_image']['visibility'] = 'public'
|
||||||
self.assertRaises(exception.PolicyNotAuthorized,
|
self.assertRaises(exception.PolicyNotAuthorized,
|
||||||
@ -1311,7 +1311,7 @@ class VolumeImageActionsTest(test.TestCase):
|
|||||||
@mock.patch.object(volume_api.API, "get_volume_image_metadata")
|
@mock.patch.object(volume_api.API, "get_volume_image_metadata")
|
||||||
@mock.patch.object(glance.GlanceImageService, "create")
|
@mock.patch.object(glance.GlanceImageService, "create")
|
||||||
@mock.patch.object(volume_rpcapi.VolumeAPI, "copy_volume_to_image")
|
@mock.patch.object(volume_rpcapi.VolumeAPI, "copy_volume_to_image")
|
||||||
def test_copy_volume_to_image_version_3_1(
|
def test_copy_volume_to_image_version_with_params(
|
||||||
self,
|
self,
|
||||||
mock_copy_volume_to_image,
|
mock_copy_volume_to_image,
|
||||||
mock_create,
|
mock_create,
|
||||||
@ -1323,7 +1323,7 @@ class VolumeImageActionsTest(test.TestCase):
|
|||||||
"volume_id": volume.id,
|
"volume_id": volume.id,
|
||||||
"key": "x_billing_code_license",
|
"key": "x_billing_code_license",
|
||||||
"value": "246254365"}
|
"value": "246254365"}
|
||||||
mock_create.side_effect = self.fake_image_service_create_3_1
|
mock_create.side_effect = self.fake_image_service_create_with_params
|
||||||
mock_copy_volume_to_image.side_effect = \
|
mock_copy_volume_to_image.side_effect = \
|
||||||
self.fake_rpc_copy_volume_to_image
|
self.fake_rpc_copy_volume_to_image
|
||||||
|
|
||||||
@ -1333,8 +1333,8 @@ class VolumeImageActionsTest(test.TestCase):
|
|||||||
'/v3/%s/volumes/%s/action' % (fake.PROJECT_ID, volume.id),
|
'/v3/%s/volumes/%s/action' % (fake.PROJECT_ID, volume.id),
|
||||||
use_admin_context=self.context.is_admin)
|
use_admin_context=self.context.is_admin)
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
req.headers = {'OpenStack-API-Version': 'volume 3.1'}
|
req.headers = mv.get_mv_header(mv.UPLOAD_IMAGE_PARAMS)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.1')
|
req.api_version_request = mv.get_api_version(mv.UPLOAD_IMAGE_PARAMS)
|
||||||
body = self._get_os_volume_upload_image()
|
body = self._get_os_volume_upload_image()
|
||||||
body['os-volume_upload_image']['visibility'] = 'public'
|
body['os-volume_upload_image']['visibility'] = 'public'
|
||||||
body['os-volume_upload_image']['protected'] = True
|
body['os-volume_upload_image']['protected'] = True
|
||||||
|
@ -23,6 +23,7 @@ from six.moves.urllib.parse import urlencode
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api.contrib import volume_manage
|
from cinder.api.contrib import volume_manage
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api.openstack import api_version_request as api_version
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -226,15 +227,15 @@ class VolumeManageTest(test.TestCase):
|
|||||||
self.assertEqual(body['volume']['ref'], args[3])
|
self.assertEqual(body['volume']['ref'], args[3])
|
||||||
self.assertTrue(mock_validate.called)
|
self.assertTrue(mock_validate.called)
|
||||||
|
|
||||||
def _get_resp_create(self, body, version='3.0'):
|
def _get_resp_create(self, body, version=mv.BASE_VERSION):
|
||||||
url = '/v3/%s/os-volume-manage' % fake.PROJECT_ID
|
url = '/v3/%s/os-volume-manage' % fake.PROJECT_ID
|
||||||
req = webob.Request.blank(url, base_url='http://localhost.com' + url)
|
req = webob.Request.blank(url, base_url='http://localhost.com' + url)
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
|
req.headers = mv.get_mv_header(version)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.environ['cinder.context'] = self._admin_ctxt
|
req.environ['cinder.context'] = self._admin_ctxt
|
||||||
req.body = jsonutils.dump_as_bytes(body)
|
req.body = jsonutils.dump_as_bytes(body)
|
||||||
req.headers = {'OpenStack-API-Version': 'volume %s' % version}
|
req.api_version_request = mv.get_api_version(version)
|
||||||
req.api_version_request = api_version.APIVersionRequest(version)
|
|
||||||
res = self.controller.create(req, body)
|
res = self.controller.create(req, body)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@ -244,7 +245,7 @@ class VolumeManageTest(test.TestCase):
|
|||||||
def test_manage_volume_ok_cluster(self, mock_validate, mock_api_manage):
|
def test_manage_volume_ok_cluster(self, mock_validate, mock_api_manage):
|
||||||
body = {'volume': {'cluster': 'cluster',
|
body = {'volume': {'cluster': 'cluster',
|
||||||
'ref': 'fake_ref'}}
|
'ref': 'fake_ref'}}
|
||||||
res = self._get_resp_create(body, '3.16')
|
res = self._get_resp_create(body, mv.VOLUME_MIGRATE_CLUSTER)
|
||||||
self.assertEqual(['volume'], list(res.keys()))
|
self.assertEqual(['volume'], list(res.keys()))
|
||||||
|
|
||||||
# Check that the manage API was called with the correct arguments.
|
# Check that the manage API was called with the correct arguments.
|
||||||
@ -262,7 +263,8 @@ class VolumeManageTest(test.TestCase):
|
|||||||
'cluster': 'cluster',
|
'cluster': 'cluster',
|
||||||
'ref': 'fake_ref'}}
|
'ref': 'fake_ref'}}
|
||||||
self.assertRaises(exception.InvalidInput,
|
self.assertRaises(exception.InvalidInput,
|
||||||
self._get_resp_create, body, '3.16')
|
self._get_resp_create, body,
|
||||||
|
mv.VOLUME_MIGRATE_CLUSTER)
|
||||||
|
|
||||||
def test_manage_volume_missing_host(self):
|
def test_manage_volume_missing_host(self):
|
||||||
"""Test correct failure when host is not specified."""
|
"""Test correct failure when host is not specified."""
|
||||||
@ -485,7 +487,7 @@ class VolumeManageTest(test.TestCase):
|
|||||||
"""Test managing volume to return 'creating' status in V3 API."""
|
"""Test managing volume to return 'creating' status in V3 API."""
|
||||||
body = {'volume': {'host': 'host_ok',
|
body = {'volume': {'host': 'host_ok',
|
||||||
'ref': 'fake_ref'}}
|
'ref': 'fake_ref'}}
|
||||||
res = self._get_resp_post_v3(body, '3.15')
|
res = self._get_resp_post_v3(body, mv.ETAGS)
|
||||||
self.assertEqual(http_client.ACCEPTED, res.status_int)
|
self.assertEqual(http_client.ACCEPTED, res.status_int)
|
||||||
self.assertEqual(1, mock_api_manage.call_count)
|
self.assertEqual(1, mock_api_manage.call_count)
|
||||||
self.assertEqual('creating',
|
self.assertEqual('creating',
|
||||||
|
@ -21,6 +21,7 @@ import ddt
|
|||||||
import mock
|
import mock
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import attachments as v3_attachments
|
from cinder.api.v3 import attachments as v3_attachments
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -31,8 +32,6 @@ from cinder.tests.unit import fake_constants as fake
|
|||||||
from cinder.volume import api as volume_api
|
from cinder.volume import api as volume_api
|
||||||
from cinder.volume import rpcapi as volume_rpcapi
|
from cinder.volume import rpcapi as volume_rpcapi
|
||||||
|
|
||||||
ATTACHMENTS_MICRO_VERSION = '3.27'
|
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class AttachmentsAPITestCase(test.TestCase):
|
class AttachmentsAPITestCase(test.TestCase):
|
||||||
@ -81,7 +80,7 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
def test_create_attachment(self):
|
def test_create_attachment(self):
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/attachments' %
|
req = fakes.HTTPRequest.blank('/v3/%s/attachments' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=ATTACHMENTS_MICRO_VERSION)
|
version=mv.NEW_ATTACH)
|
||||||
body = {
|
body = {
|
||||||
"attachment":
|
"attachment":
|
||||||
{
|
{
|
||||||
@ -104,7 +103,7 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
mock_update.return_value = fake_connector
|
mock_update.return_value = fake_connector
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/attachments/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/attachments/%s' %
|
||||||
(fake.PROJECT_ID, self.attachment1.id),
|
(fake.PROJECT_ID, self.attachment1.id),
|
||||||
version=ATTACHMENTS_MICRO_VERSION,
|
version=mv.NEW_ATTACH,
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
body = {
|
body = {
|
||||||
"attachment":
|
"attachment":
|
||||||
@ -124,7 +123,7 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
mock_get.return_value = {'project_id': fake.PROJECT2_ID}
|
mock_get.return_value = {'project_id': fake.PROJECT2_ID}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/attachments/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/attachments/%s' %
|
||||||
(fake.PROJECT_ID, self.attachment1.id),
|
(fake.PROJECT_ID, self.attachment1.id),
|
||||||
version=ATTACHMENTS_MICRO_VERSION,
|
version=mv.NEW_ATTACH,
|
||||||
use_admin_context=False)
|
use_admin_context=False)
|
||||||
body = {
|
body = {
|
||||||
"attachment":
|
"attachment":
|
||||||
@ -139,7 +138,8 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
self.controller.delete, req,
|
self.controller.delete, req,
|
||||||
self.attachment1.id)
|
self.attachment1.id)
|
||||||
|
|
||||||
@ddt.data('3.30', '3.31', '3.34')
|
@ddt.data(mv.get_prior_version(mv.RESOURCE_FILTER),
|
||||||
|
mv.RESOURCE_FILTER, mv.LIKE_FILTER)
|
||||||
@mock.patch('cinder.api.common.reject_invalid_filters')
|
@mock.patch('cinder.api.common.reject_invalid_filters')
|
||||||
def test_attachment_list_with_general_filter(self, version, mock_update):
|
def test_attachment_list_with_general_filter(self, version, mock_update):
|
||||||
url = '/v3/%s/attachments' % fake.PROJECT_ID
|
url = '/v3/%s/attachments' % fake.PROJECT_ID
|
||||||
@ -148,8 +148,8 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
use_admin_context=False)
|
use_admin_context=False)
|
||||||
self.controller.index(req)
|
self.controller.index(req)
|
||||||
|
|
||||||
if version != '3.30':
|
if version != mv.get_prior_version(mv.RESOURCE_FILTER):
|
||||||
support_like = True if version == '3.34' else False
|
support_like = True if version == mv.LIKE_FILTER else False
|
||||||
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
||||||
mock.ANY, 'attachment',
|
mock.ANY, 'attachment',
|
||||||
support_like)
|
support_like)
|
||||||
@ -164,7 +164,7 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
attach_status=status)
|
attach_status=status)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/attachments/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/attachments/%s' %
|
||||||
(fake.PROJECT_ID, attachment.id),
|
(fake.PROJECT_ID, attachment.id),
|
||||||
version=ATTACHMENTS_MICRO_VERSION,
|
version=mv.NEW_ATTACH,
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
|
|
||||||
self.controller.delete(req, attachment.id)
|
self.controller.delete(req, attachment.id)
|
||||||
@ -201,7 +201,7 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
def test_create_attachment_without_resource_uuid(self, resource_uuid):
|
def test_create_attachment_without_resource_uuid(self, resource_uuid):
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/attachments' %
|
req = fakes.HTTPRequest.blank('/v3/%s/attachments' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=ATTACHMENTS_MICRO_VERSION)
|
version=mv.NEW_ATTACH)
|
||||||
body = {
|
body = {
|
||||||
"attachment":
|
"attachment":
|
||||||
{
|
{
|
||||||
@ -220,7 +220,7 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
if is_detail:
|
if is_detail:
|
||||||
url = '/v3/%s/groups/detail' % fake.PROJECT_ID
|
url = '/v3/%s/groups/detail' % fake.PROJECT_ID
|
||||||
list_func = self.controller.detail
|
list_func = self.controller.detail
|
||||||
req = fakes.HTTPRequest.blank(url, version=ATTACHMENTS_MICRO_VERSION,
|
req = fakes.HTTPRequest.blank(url, version=mv.NEW_ATTACH,
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
res_dict = list_func(req)
|
res_dict = list_func(req)
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_list_attachments_with_limit(self):
|
def test_list_attachments_with_limit(self):
|
||||||
url = '/v3/%s/attachments?limit=1' % fake.PROJECT_ID
|
url = '/v3/%s/attachments?limit=1' % fake.PROJECT_ID
|
||||||
req = fakes.HTTPRequest.blank(url, version=ATTACHMENTS_MICRO_VERSION,
|
req = fakes.HTTPRequest.blank(url, version=mv.NEW_ATTACH,
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
|
|
||||||
@ -241,7 +241,7 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
def test_list_attachments_with_marker(self):
|
def test_list_attachments_with_marker(self):
|
||||||
url = '/v3/%s/attachments?marker=%s' % (fake.PROJECT_ID,
|
url = '/v3/%s/attachments?marker=%s' % (fake.PROJECT_ID,
|
||||||
self.attachment3.id)
|
self.attachment3.id)
|
||||||
req = fakes.HTTPRequest.blank(url, version=ATTACHMENTS_MICRO_VERSION,
|
req = fakes.HTTPRequest.blank(url, version=mv.NEW_ATTACH,
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
def test_list_attachments_with_sort(self, sort_dir):
|
def test_list_attachments_with_sort(self, sort_dir):
|
||||||
url = '/v3/%s/attachments?sort_key=id&sort_dir=%s' % (fake.PROJECT_ID,
|
url = '/v3/%s/attachments?sort_key=id&sort_dir=%s' % (fake.PROJECT_ID,
|
||||||
sort_dir)
|
sort_dir)
|
||||||
req = fakes.HTTPRequest.blank(url, version=ATTACHMENTS_MICRO_VERSION,
|
req = fakes.HTTPRequest.blank(url, version=mv.NEW_ATTACH,
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ class AttachmentsAPITestCase(test.TestCase):
|
|||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_list_attachment_with_tenants(self, admin, request_url, count):
|
def test_list_attachment_with_tenants(self, admin, request_url, count):
|
||||||
url = '/v3/%s/attachments%s' % (fake.PROJECT_ID, request_url)
|
url = '/v3/%s/attachments%s' % (fake.PROJECT_ID, request_url)
|
||||||
req = fakes.HTTPRequest.blank(url, version=ATTACHMENTS_MICRO_VERSION,
|
req = fakes.HTTPRequest.blank(url, version=mv.NEW_ATTACH,
|
||||||
use_admin_context=admin)
|
use_admin_context=admin)
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import ddt
|
|||||||
import mock
|
import mock
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api.openstack import api_version_request as api_version
|
||||||
from cinder.api.v3 import backups
|
from cinder.api.v3 import backups
|
||||||
from cinder.api.views import backups as backup_view
|
from cinder.api.views import backups as backup_view
|
||||||
@ -44,7 +45,7 @@ class BackupsControllerAPITestCase(test.TestCase):
|
|||||||
is_admin=True)
|
is_admin=True)
|
||||||
self.controller = backups.BackupsController()
|
self.controller = backups.BackupsController()
|
||||||
|
|
||||||
def _fake_update_request(self, backup_id, version='3.9'):
|
def _fake_update_request(self, backup_id, version=mv.BACKUP_UPDATE):
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/backups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/backups/%s/update' %
|
||||||
(fake.PROJECT_ID, backup_id))
|
(fake.PROJECT_ID, backup_id))
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
@ -54,7 +55,8 @@ class BackupsControllerAPITestCase(test.TestCase):
|
|||||||
return req
|
return req
|
||||||
|
|
||||||
def test_update_wrong_version(self):
|
def test_update_wrong_version(self):
|
||||||
req = self._fake_update_request(fake.BACKUP_ID, version='3.6')
|
req = self._fake_update_request(
|
||||||
|
fake.BACKUP_ID, version=mv.get_prior_version(mv.BACKUP_UPDATE))
|
||||||
body = {"backup": {"name": "Updated Test Name", }}
|
body = {"backup": {"name": "Updated Test Name", }}
|
||||||
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
||||||
self.controller.update, req, fake.BACKUP_ID,
|
self.controller.update, req, fake.BACKUP_ID,
|
||||||
@ -86,7 +88,9 @@ class BackupsControllerAPITestCase(test.TestCase):
|
|||||||
self.controller.update,
|
self.controller.update,
|
||||||
req, fake.BACKUP_ID, body)
|
req, fake.BACKUP_ID, body)
|
||||||
|
|
||||||
@ddt.data('3.30', '3.31', '3.34')
|
@ddt.data(mv.get_prior_version(mv.RESOURCE_FILTER),
|
||||||
|
mv.RESOURCE_FILTER,
|
||||||
|
mv.LIKE_FILTER)
|
||||||
@mock.patch('cinder.api.common.reject_invalid_filters')
|
@mock.patch('cinder.api.common.reject_invalid_filters')
|
||||||
def test_backup_list_with_general_filter(self, version, mock_update):
|
def test_backup_list_with_general_filter(self, version, mock_update):
|
||||||
url = '/v3/%s/backups' % fake.PROJECT_ID
|
url = '/v3/%s/backups' % fake.PROJECT_ID
|
||||||
@ -95,13 +99,14 @@ class BackupsControllerAPITestCase(test.TestCase):
|
|||||||
use_admin_context=False)
|
use_admin_context=False)
|
||||||
self.controller.index(req)
|
self.controller.index(req)
|
||||||
|
|
||||||
if version != '3.30':
|
if version != mv.get_prior_version(mv.RESOURCE_FILTER):
|
||||||
support_like = True if version == '3.34' else False
|
support_like = True if version == mv.LIKE_FILTER else False
|
||||||
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
||||||
mock.ANY, 'backup',
|
mock.ANY, 'backup',
|
||||||
support_like)
|
support_like)
|
||||||
|
|
||||||
@ddt.data('3.36', '3.37')
|
@ddt.data(mv.get_prior_version(mv.BACKUP_SORT_NAME),
|
||||||
|
mv.BACKUP_SORT_NAME)
|
||||||
def test_backup_list_with_name(self, version):
|
def test_backup_list_with_name(self, version):
|
||||||
backup1 = test_utils.create_backup(
|
backup1 = test_utils.create_backup(
|
||||||
self.ctxt, display_name='b_test_name',
|
self.ctxt, display_name='b_test_name',
|
||||||
@ -111,7 +116,7 @@ class BackupsControllerAPITestCase(test.TestCase):
|
|||||||
status=fields.BackupStatus.AVAILABLE)
|
status=fields.BackupStatus.AVAILABLE)
|
||||||
url = '/v3/%s/backups?sort_key=name' % fake.PROJECT_ID
|
url = '/v3/%s/backups?sort_key=name' % fake.PROJECT_ID
|
||||||
req = fakes.HTTPRequest.blank(url, version=version)
|
req = fakes.HTTPRequest.blank(url, version=version)
|
||||||
if version == '3.36':
|
if version == mv.get_prior_version(mv.BACKUP_SORT_NAME):
|
||||||
self.assertRaises(exception.InvalidInput,
|
self.assertRaises(exception.InvalidInput,
|
||||||
self.controller.index,
|
self.controller.index,
|
||||||
req)
|
req)
|
||||||
|
@ -21,6 +21,7 @@ import mock
|
|||||||
from oslo_utils import versionutils
|
from oslo_utils import versionutils
|
||||||
|
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api.openstack import api_version_request as api_version
|
||||||
from cinder.api.v3 import clusters
|
from cinder.api.v3 import clusters
|
||||||
from cinder import context
|
from cinder import context
|
||||||
@ -78,7 +79,7 @@ EXPECTED = [{'created_at': datetime.datetime(2016, 6, 1, 2, 46, 28),
|
|||||||
|
|
||||||
|
|
||||||
class FakeRequest(object):
|
class FakeRequest(object):
|
||||||
def __init__(self, is_admin=True, version='3.7', **kwargs):
|
def __init__(self, is_admin=True, version=mv.CLUSTER_SUPPORT, **kwargs):
|
||||||
self.GET = kwargs
|
self.GET = kwargs
|
||||||
self.headers = {'OpenStack-API-Version': 'volume ' + version}
|
self.headers = {'OpenStack-API-Version': 'volume ' + version}
|
||||||
self.api_version_request = api_version.APIVersionRequest(version)
|
self.api_version_request = api_version.APIVersionRequest(version)
|
||||||
@ -108,8 +109,10 @@ class ClustersTestCase(test.TestCase):
|
|||||||
REPLICATION_FILTERS = ({'replication_status': 'error'}, {'frozen': True},
|
REPLICATION_FILTERS = ({'replication_status': 'error'}, {'frozen': True},
|
||||||
{'active_backend_id': 'replication'})
|
{'active_backend_id': 'replication'})
|
||||||
|
|
||||||
def _get_expected(self, version='3.8'):
|
def _get_expected(self,
|
||||||
if versionutils.convert_version_to_tuple(version) >= (3, 19):
|
version=mv.get_prior_version(mv.REPLICATION_CLUSTER)):
|
||||||
|
if (versionutils.convert_version_to_tuple(version) >=
|
||||||
|
versionutils.convert_version_to_tuple(mv.REPLICATION_CLUSTER)):
|
||||||
return EXPECTED
|
return EXPECTED
|
||||||
|
|
||||||
expect = []
|
expect = []
|
||||||
@ -130,7 +133,7 @@ class ClustersTestCase(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch('cinder.db.cluster_get_all', return_value=CLUSTERS_ORM)
|
@mock.patch('cinder.db.cluster_get_all', return_value=CLUSTERS_ORM)
|
||||||
def _test_list(self, get_all_mock, detailed, filters=None, expected=None,
|
def _test_list(self, get_all_mock, detailed, filters=None, expected=None,
|
||||||
version='3.8'):
|
version=mv.get_prior_version(mv.REPLICATION_CLUSTER)):
|
||||||
filters = filters or {}
|
filters = filters or {}
|
||||||
req = FakeRequest(version=version, **filters)
|
req = FakeRequest(version=version, **filters)
|
||||||
method = getattr(self.controller, 'detail' if detailed else 'index')
|
method = getattr(self.controller, 'detail' if detailed else 'index')
|
||||||
@ -187,14 +190,13 @@ class ClustersTestCase(test.TestCase):
|
|||||||
"""Verify the wrong version so that user can't list clusters."""
|
"""Verify the wrong version so that user can't list clusters."""
|
||||||
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
||||||
self._test_list, detailed=detailed,
|
self._test_list, detailed=detailed,
|
||||||
version='3.6')
|
version=mv.get_prior_version(mv.CLUSTER_SUPPORT))
|
||||||
|
|
||||||
@ddt.data(*REPLICATION_FILTERS)
|
@ddt.data(*REPLICATION_FILTERS)
|
||||||
def test_index_detail_replication_new_fields(self, filters):
|
def test_index_detail_replication_new_fields(self, filters):
|
||||||
version = '3.26'
|
expected = {'clusters': self._get_expected(mv.REPLICATION_CLUSTER)}
|
||||||
expected = {'clusters': self._get_expected(version)}
|
|
||||||
self._test_list(detailed=True, filters=filters, expected=expected,
|
self._test_list(detailed=True, filters=filters, expected=expected,
|
||||||
version=version)
|
version=mv.REPLICATION_CLUSTER)
|
||||||
|
|
||||||
@ddt.data(*REPLICATION_FILTERS)
|
@ddt.data(*REPLICATION_FILTERS)
|
||||||
def test_index_summary_replication_new_fields(self, filters):
|
def test_index_summary_replication_new_fields(self, filters):
|
||||||
@ -209,7 +211,7 @@ class ClustersTestCase(test.TestCase):
|
|||||||
'replication_status': 'error',
|
'replication_status': 'error',
|
||||||
'status': 'disabled'}]}
|
'status': 'disabled'}]}
|
||||||
self._test_list(detailed=False, filters=filters, expected=expected,
|
self._test_list(detailed=False, filters=filters, expected=expected,
|
||||||
version='3.26')
|
version=mv.REPLICATION_CLUSTER)
|
||||||
|
|
||||||
@mock.patch('cinder.db.sqlalchemy.api.cluster_get',
|
@mock.patch('cinder.db.sqlalchemy.api.cluster_get',
|
||||||
return_value=CLUSTERS_ORM[0])
|
return_value=CLUSTERS_ORM[0])
|
||||||
@ -232,7 +234,7 @@ class ClustersTestCase(test.TestCase):
|
|||||||
self.controller.show, req, 'name')
|
self.controller.show, req, 'name')
|
||||||
|
|
||||||
def test_show_wrong_version(self):
|
def test_show_wrong_version(self):
|
||||||
req = FakeRequest(version='3.5')
|
req = FakeRequest(version=mv.get_prior_version(mv.CLUSTER_SUPPORT))
|
||||||
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
||||||
self.controller.show, req, 'name')
|
self.controller.show, req, 'name')
|
||||||
|
|
||||||
@ -307,6 +309,6 @@ class ClustersTestCase(test.TestCase):
|
|||||||
|
|
||||||
@ddt.data('enable', 'disable')
|
@ddt.data('enable', 'disable')
|
||||||
def test_update_wrong_version(self, action):
|
def test_update_wrong_version(self, action):
|
||||||
req = FakeRequest(version='3.5')
|
req = FakeRequest(version=mv.get_prior_version(mv.CLUSTER_SUPPORT))
|
||||||
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
||||||
self.controller.update, req, action, {})
|
self.controller.update, req, action, {})
|
||||||
|
@ -15,6 +15,7 @@ import ddt
|
|||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api.openstack import api_version_request as api_version
|
||||||
from cinder.api.v3 import consistencygroups
|
from cinder.api.v3 import consistencygroups
|
||||||
from cinder import context
|
from cinder import context
|
||||||
@ -72,9 +73,10 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/consistencygroups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/consistencygroups/%s/update' %
|
||||||
(fake.PROJECT_ID, consistencygroup.id))
|
(fake.PROJECT_ID, consistencygroup.id))
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
req.headers = mv.get_mv_header(mv.CG_UPDATE_BLANK_PROPERTIES)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume 3.6'
|
req.api_version_request = mv.get_api_version(
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.6')
|
mv.CG_UPDATE_BLANK_PROPERTIES)
|
||||||
body = {"consistencygroup": {"name": "",
|
body = {"consistencygroup": {"name": "",
|
||||||
"description": "",
|
"description": "",
|
||||||
"add_volumes": None,
|
"add_volumes": None,
|
||||||
@ -118,9 +120,10 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/consistencygroups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/consistencygroups/%s/update' %
|
||||||
(fake.PROJECT_ID, consistencygroup.id))
|
(fake.PROJECT_ID, consistencygroup.id))
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
req.headers = mv.get_mv_header(mv.CG_UPDATE_BLANK_PROPERTIES)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume 3.6'
|
req.api_version_request = mv.get_api_version(
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.6')
|
mv.CG_UPDATE_BLANK_PROPERTIES)
|
||||||
body = {"consistencygroup": {"name": None,
|
body = {"consistencygroup": {"name": None,
|
||||||
"description": None,
|
"description": None,
|
||||||
"add_volumes": None,
|
"add_volumes": None,
|
||||||
@ -132,16 +135,20 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
|||||||
req, consistencygroup.id, body)
|
req, consistencygroup.id, body)
|
||||||
consistencygroup.destroy()
|
consistencygroup.destroy()
|
||||||
|
|
||||||
def test_update_consistencygroup_all_empty_parameters_not_version_36(self):
|
def test_update_consistencygroup_all_empty_parameters_not_version_ok(self):
|
||||||
consistencygroup = self._create_consistencygroup(
|
consistencygroup = self._create_consistencygroup(
|
||||||
ctxt=self.ctxt,
|
ctxt=self.ctxt,
|
||||||
status=fields.ConsistencyGroupStatus.AVAILABLE)
|
status=fields.ConsistencyGroupStatus.AVAILABLE)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/consistencygroups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/consistencygroups/%s/update' %
|
||||||
(fake.PROJECT_ID, consistencygroup.id))
|
(fake.PROJECT_ID, consistencygroup.id))
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
|
non_supported_version = mv.get_prior_version(
|
||||||
|
mv.CG_UPDATE_BLANK_PROPERTIES)
|
||||||
|
req.headers = mv.get_mv_header(non_supported_version)
|
||||||
|
req.api_version_request = mv.get_api_version(non_supported_version)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume 3.5'
|
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.5')
|
|
||||||
body = {"consistencygroup": {"name": None,
|
body = {"consistencygroup": {"name": None,
|
||||||
"description": None,
|
"description": None,
|
||||||
"add_volumes": None,
|
"add_volumes": None,
|
||||||
@ -160,9 +167,13 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/consistencygroups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/consistencygroups/%s/update' %
|
||||||
(fake.PROJECT_ID, consistencygroup.id))
|
(fake.PROJECT_ID, consistencygroup.id))
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
|
non_supported_version = mv.get_prior_version(
|
||||||
|
mv.CG_UPDATE_BLANK_PROPERTIES)
|
||||||
|
req.headers = mv.get_mv_header(non_supported_version)
|
||||||
|
req.api_version_request = mv.get_api_version(non_supported_version)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume 3.5'
|
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.5')
|
|
||||||
body = None
|
body = None
|
||||||
self.assertRaisesRegexp(webob.exc.HTTPBadRequest,
|
self.assertRaisesRegexp(webob.exc.HTTPBadRequest,
|
||||||
"Missing request body",
|
"Missing request body",
|
||||||
@ -177,9 +188,13 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/consistencygroups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/consistencygroups/%s/update' %
|
||||||
(fake.PROJECT_ID, consistencygroup.id))
|
(fake.PROJECT_ID, consistencygroup.id))
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
|
non_supported_version = mv.get_prior_version(
|
||||||
|
mv.CG_UPDATE_BLANK_PROPERTIES)
|
||||||
|
req.headers = mv.get_mv_header(non_supported_version)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume 3.5'
|
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.5')
|
req.api_version_request = mv.get_api_version(non_supported_version)
|
||||||
body = {"consistencygroup": {"name": "my_fake_cg",
|
body = {"consistencygroup": {"name": "my_fake_cg",
|
||||||
"description": "fake consistency group",
|
"description": "fake consistency group",
|
||||||
"add_volumes": "volume-uuid-1",
|
"add_volumes": "volume-uuid-1",
|
||||||
|
@ -22,6 +22,7 @@ import mock
|
|||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import group_snapshots as v3_group_snapshots
|
from cinder.api.v3 import group_snapshots as v3_group_snapshots
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import db
|
from cinder import db
|
||||||
@ -35,9 +36,6 @@ from cinder.tests.unit import fake_constants as fake
|
|||||||
from cinder.tests.unit import utils
|
from cinder.tests.unit import utils
|
||||||
import cinder.volume
|
import cinder.volume
|
||||||
|
|
||||||
GROUP_MICRO_VERSION = '3.14'
|
|
||||||
SUPPORT_FILTER_VERSION = '3.29'
|
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class GroupSnapshotsAPITestCase(test.TestCase):
|
class GroupSnapshotsAPITestCase(test.TestCase):
|
||||||
@ -76,7 +74,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
self.context, group_id=self.group.id)
|
self.context, group_id=self.group.id)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
||||||
(fake.PROJECT_ID, group_snapshot.id),
|
(fake.PROJECT_ID, group_snapshot.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
res_dict = self.controller.show(req, group_snapshot.id)
|
res_dict = self.controller.show(req, group_snapshot.id)
|
||||||
|
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
@ -95,7 +93,8 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
url = '/v3/%s/group_snapshots?limit=1' % fake.PROJECT_ID
|
url = '/v3/%s/group_snapshots?limit=1' % fake.PROJECT_ID
|
||||||
if is_detail:
|
if is_detail:
|
||||||
url = '/v3/%s/group_snapshots/detail?limit=1' % fake.PROJECT_ID
|
url = '/v3/%s/group_snapshots/detail?limit=1' % fake.PROJECT_ID
|
||||||
req = fakes.HTTPRequest.blank(url, version=SUPPORT_FILTER_VERSION)
|
req = fakes.HTTPRequest.blank(url,
|
||||||
|
version=mv.GROUP_SNAPSHOT_PAGINATION)
|
||||||
if is_detail:
|
if is_detail:
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
else:
|
else:
|
||||||
@ -122,7 +121,8 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
url = '/v3/%s/group_snapshots?offset=1' % fake.PROJECT_ID
|
url = '/v3/%s/group_snapshots?offset=1' % fake.PROJECT_ID
|
||||||
if is_detail:
|
if is_detail:
|
||||||
url = '/v3/%s/group_snapshots/detail?offset=1' % fake.PROJECT_ID
|
url = '/v3/%s/group_snapshots/detail?offset=1' % fake.PROJECT_ID
|
||||||
req = fakes.HTTPRequest.blank(url, version=SUPPORT_FILTER_VERSION)
|
req = fakes.HTTPRequest.blank(url,
|
||||||
|
version=mv.GROUP_SNAPSHOT_PAGINATION)
|
||||||
if is_detail:
|
if is_detail:
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
else:
|
else:
|
||||||
@ -146,7 +146,8 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
if is_detail:
|
if is_detail:
|
||||||
url = ('/v3/%s/group_snapshots/detail?offset=234523423455454' %
|
url = ('/v3/%s/group_snapshots/detail?offset=234523423455454' %
|
||||||
fake.PROJECT_ID)
|
fake.PROJECT_ID)
|
||||||
req = fakes.HTTPRequest.blank(url, version=SUPPORT_FILTER_VERSION)
|
req = fakes.HTTPRequest.blank(url,
|
||||||
|
version=mv.GROUP_SNAPSHOT_PAGINATION)
|
||||||
if is_detail:
|
if is_detail:
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.detail,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.detail,
|
||||||
req)
|
req)
|
||||||
@ -164,7 +165,8 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
if is_detail:
|
if is_detail:
|
||||||
url = ('/v3/%s/group_snapshots/detail?limit=2&offset=1' %
|
url = ('/v3/%s/group_snapshots/detail?limit=2&offset=1' %
|
||||||
fake.PROJECT_ID)
|
fake.PROJECT_ID)
|
||||||
req = fakes.HTTPRequest.blank(url, version=SUPPORT_FILTER_VERSION)
|
req = fakes.HTTPRequest.blank(url,
|
||||||
|
version=mv.GROUP_SNAPSHOT_PAGINATION)
|
||||||
if is_detail:
|
if is_detail:
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
else:
|
else:
|
||||||
@ -184,7 +186,9 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
res_dict['group_snapshots'][0].keys())
|
res_dict['group_snapshots'][0].keys())
|
||||||
group_snapshot.destroy()
|
group_snapshot.destroy()
|
||||||
|
|
||||||
@ddt.data('3.30', '3.31', '3.34')
|
@ddt.data(mv.get_prior_version(mv.RESOURCE_FILTER),
|
||||||
|
mv.RESOURCE_FILTER,
|
||||||
|
mv.LIKE_FILTER)
|
||||||
@mock.patch('cinder.api.common.reject_invalid_filters')
|
@mock.patch('cinder.api.common.reject_invalid_filters')
|
||||||
def test_group_snapshot_list_with_general_filter(self,
|
def test_group_snapshot_list_with_general_filter(self,
|
||||||
version, mock_update):
|
version, mock_update):
|
||||||
@ -194,8 +198,8 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
use_admin_context=False)
|
use_admin_context=False)
|
||||||
self.controller.index(req)
|
self.controller.index(req)
|
||||||
|
|
||||||
if version != '3.30':
|
if version != mv.get_prior_version(mv.RESOURCE_FILTER):
|
||||||
support_like = True if version == '3.34' else False
|
support_like = True if version == mv.LIKE_FILTER else False
|
||||||
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
||||||
mock.ANY, 'group_snapshot',
|
mock.ANY, 'group_snapshot',
|
||||||
support_like)
|
support_like)
|
||||||
@ -209,7 +213,8 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
url = ('/v3/%s/group_snapshots/detail?'
|
url = ('/v3/%s/group_snapshots/detail?'
|
||||||
'all_tenants=True&id=%s') % (fake.PROJECT_ID,
|
'all_tenants=True&id=%s') % (fake.PROJECT_ID,
|
||||||
self.g_snapshots_array[0].id)
|
self.g_snapshots_array[0].id)
|
||||||
req = fakes.HTTPRequest.blank(url, version=SUPPORT_FILTER_VERSION,
|
req = fakes.HTTPRequest.blank(url,
|
||||||
|
version=mv.GROUP_SNAPSHOT_PAGINATION,
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
if is_detail:
|
if is_detail:
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
@ -226,10 +231,10 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
self.assertNotIn('description',
|
self.assertNotIn('description',
|
||||||
res_dict['group_snapshots'][0].keys())
|
res_dict['group_snapshots'][0].keys())
|
||||||
|
|
||||||
@ddt.data({'is_detail': True, 'version': GROUP_MICRO_VERSION},
|
@ddt.data({'is_detail': True, 'version': mv.GROUP_SNAPSHOTS},
|
||||||
{'is_detail': False, 'version': GROUP_MICRO_VERSION},
|
{'is_detail': False, 'version': mv.GROUP_SNAPSHOTS},
|
||||||
{'is_detail': True, 'version': '3.28'},
|
{'is_detail': True, 'version': mv.POOL_FILTER},
|
||||||
{'is_detail': False, 'version': '3.28'},)
|
{'is_detail': False, 'version': mv.POOL_FILTER},)
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_list_group_snapshot_with_filter_previous_version(self, is_detail,
|
def test_list_group_snapshot_with_filter_previous_version(self, is_detail,
|
||||||
version):
|
version):
|
||||||
@ -257,7 +262,8 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
if is_detail:
|
if is_detail:
|
||||||
url = ('/v3/%s/group_snapshots/detail?sort=id:asc' %
|
url = ('/v3/%s/group_snapshots/detail?sort=id:asc' %
|
||||||
fake.PROJECT_ID)
|
fake.PROJECT_ID)
|
||||||
req = fakes.HTTPRequest.blank(url, version=SUPPORT_FILTER_VERSION)
|
req = fakes.HTTPRequest.blank(url,
|
||||||
|
version=mv.GROUP_SNAPSHOT_PAGINATION)
|
||||||
expect_result = [snapshot.id for snapshot in self.g_snapshots_array]
|
expect_result = [snapshot.id for snapshot in self.g_snapshots_array]
|
||||||
expect_result.sort()
|
expect_result.sort()
|
||||||
if is_detail:
|
if is_detail:
|
||||||
@ -282,7 +288,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
||||||
(fake.PROJECT_ID,
|
(fake.PROJECT_ID,
|
||||||
fake.WILL_NOT_BE_FOUND_ID),
|
fake.WILL_NOT_BE_FOUND_ID),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
self.assertRaises(exception.GroupSnapshotNotFound,
|
self.assertRaises(exception.GroupSnapshotNotFound,
|
||||||
self.controller.show,
|
self.controller.show,
|
||||||
req, fake.WILL_NOT_BE_FOUND_ID)
|
req, fake.WILL_NOT_BE_FOUND_ID)
|
||||||
@ -294,7 +300,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
else:
|
else:
|
||||||
request_url = '/v3/%s/group_snapshots'
|
request_url = '/v3/%s/group_snapshots'
|
||||||
req = fakes.HTTPRequest.blank(request_url % fake.PROJECT_ID,
|
req = fakes.HTTPRequest.blank(request_url % fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
if is_detail:
|
if is_detail:
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
else:
|
else:
|
||||||
@ -326,7 +332,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
"group_id": self.group.id}}
|
"group_id": self.group.id}}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
res_dict = self.controller.create(req, body)
|
res_dict = self.controller.create(req, body)
|
||||||
|
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
@ -356,7 +362,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
"group_id": group.id}}
|
"group_id": group.id}}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
||||||
req, body)
|
req, body)
|
||||||
self.assertTrue(mock_validate.called)
|
self.assertTrue(mock_validate.called)
|
||||||
@ -369,7 +375,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
# omit body from the request
|
# omit body from the request
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
||||||
req, None)
|
req, None)
|
||||||
|
|
||||||
@ -383,7 +389,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
"group_id": self.group.id}}
|
"group_id": self.group.id}}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
||||||
req, body)
|
req, body)
|
||||||
|
|
||||||
@ -397,7 +403,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
"group_id": self.group.id}}
|
"group_id": self.group.id}}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
self.assertRaises(exception.GroupSnapshotNotFound,
|
self.assertRaises(exception.GroupSnapshotNotFound,
|
||||||
self.controller.create,
|
self.controller.create,
|
||||||
req, body)
|
req, body)
|
||||||
@ -413,7 +419,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
"group_id": empty_group.id}}
|
"group_id": empty_group.id}}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
|
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
||||||
req, body)
|
req, body)
|
||||||
@ -426,7 +432,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
status=fields.GroupSnapshotStatus.AVAILABLE)
|
status=fields.GroupSnapshotStatus.AVAILABLE)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
||||||
(fake.PROJECT_ID, group_snapshot.id),
|
(fake.PROJECT_ID, group_snapshot.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
res_dict = self.controller.delete(req, group_snapshot.id)
|
res_dict = self.controller.delete(req, group_snapshot.id)
|
||||||
|
|
||||||
group_snapshot = objects.GroupSnapshot.get_by_id(self.context,
|
group_snapshot = objects.GroupSnapshot.get_by_id(self.context,
|
||||||
@ -450,7 +456,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
volume_type_ids=[fake.VOLUME_TYPE_ID],)
|
volume_type_ids=[fake.VOLUME_TYPE_ID],)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
||||||
(fake.PROJECT_ID, group_snapshot.id),
|
(fake.PROJECT_ID, group_snapshot.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.delete,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.delete,
|
||||||
req, group_snapshot.id)
|
req, group_snapshot.id)
|
||||||
|
|
||||||
@ -461,7 +467,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
||||||
(fake.PROJECT_ID,
|
(fake.PROJECT_ID,
|
||||||
fake.WILL_NOT_BE_FOUND_ID),
|
fake.WILL_NOT_BE_FOUND_ID),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
self.assertRaises(exception.GroupSnapshotNotFound,
|
self.assertRaises(exception.GroupSnapshotNotFound,
|
||||||
self.controller.delete,
|
self.controller.delete,
|
||||||
req, fake.WILL_NOT_BE_FOUND_ID)
|
req, fake.WILL_NOT_BE_FOUND_ID)
|
||||||
@ -473,19 +479,20 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
status='invalid')
|
status='invalid')
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
|
||||||
(fake.PROJECT_ID, group_snapshot.id),
|
(fake.PROJECT_ID, group_snapshot.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.delete,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.delete,
|
||||||
req, group_snapshot.id)
|
req, group_snapshot.id)
|
||||||
|
|
||||||
group_snapshot.destroy()
|
group_snapshot.destroy()
|
||||||
|
|
||||||
@ddt.data(('3.11', 'fake_snapshot_001',
|
@ddt.data((mv.GROUP_TYPE, 'fake_snapshot_001',
|
||||||
fields.GroupSnapshotStatus.AVAILABLE,
|
fields.GroupSnapshotStatus.AVAILABLE,
|
||||||
exception.VersionNotFoundForAPIMethod),
|
exception.VersionNotFoundForAPIMethod),
|
||||||
('3.18', 'fake_snapshot_001',
|
(mv.get_prior_version(mv.GROUP_SNAPSHOT_RESET_STATUS),
|
||||||
|
'fake_snapshot_001',
|
||||||
fields.GroupSnapshotStatus.AVAILABLE,
|
fields.GroupSnapshotStatus.AVAILABLE,
|
||||||
exception.VersionNotFoundForAPIMethod),
|
exception.VersionNotFoundForAPIMethod),
|
||||||
('3.19', 'fake_snapshot_001',
|
(mv.GROUP_SNAPSHOT_RESET_STATUS, 'fake_snapshot_001',
|
||||||
fields.GroupSnapshotStatus.AVAILABLE,
|
fields.GroupSnapshotStatus.AVAILABLE,
|
||||||
exception.GroupSnapshotNotFound))
|
exception.GroupSnapshotNotFound))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
@ -509,7 +516,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
status=fields.GroupSnapshotStatus.CREATING)
|
status=fields.GroupSnapshotStatus.CREATING)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s/action' %
|
||||||
(fake.PROJECT_ID, group_snapshot.id),
|
(fake.PROJECT_ID, group_snapshot.id),
|
||||||
version='3.19')
|
version=mv.GROUP_SNAPSHOT_RESET_STATUS)
|
||||||
body = {"reset_status": {
|
body = {"reset_status": {
|
||||||
"status": "invalid_test_status"
|
"status": "invalid_test_status"
|
||||||
}}
|
}}
|
||||||
@ -525,7 +532,7 @@ class GroupSnapshotsAPITestCase(test.TestCase):
|
|||||||
status=fields.GroupSnapshotStatus.CREATING)
|
status=fields.GroupSnapshotStatus.CREATING)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s/action' %
|
||||||
(fake.PROJECT_ID, group_snapshot.id),
|
(fake.PROJECT_ID, group_snapshot.id),
|
||||||
version='3.19')
|
version=mv.GROUP_SNAPSHOT_RESET_STATUS)
|
||||||
body = {"reset_status": {
|
body = {"reset_status": {
|
||||||
"status": fields.GroupSnapshotStatus.AVAILABLE
|
"status": fields.GroupSnapshotStatus.AVAILABLE
|
||||||
}}
|
}}
|
||||||
|
@ -21,12 +21,11 @@ from cinder import db
|
|||||||
from cinder import rpc
|
from cinder import rpc
|
||||||
from cinder import test
|
from cinder import test
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import group_specs as v3_group_specs
|
from cinder.api.v3 import group_specs as v3_group_specs
|
||||||
from cinder.tests.unit.api import fakes
|
from cinder.tests.unit.api import fakes
|
||||||
from cinder.tests.unit import fake_constants as fake
|
from cinder.tests.unit import fake_constants as fake
|
||||||
|
|
||||||
GROUP_TYPE_MICRO_VERSION = '3.11'
|
|
||||||
|
|
||||||
fake_group_specs = {
|
fake_group_specs = {
|
||||||
'key1': 'value1',
|
'key1': 'value1',
|
||||||
'key2': 'value2'
|
'key2': 'value2'
|
||||||
@ -71,7 +70,7 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res_dict = self.controller.index(req, fake.GROUP_ID)
|
res_dict = self.controller.index(req, fake.GROUP_ID)
|
||||||
group_specs_dict = res_dict['group_specs']
|
group_specs_dict = res_dict['group_specs']
|
||||||
@ -90,7 +89,7 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
self.controller.create(req, fake.GROUP_ID, create_fake_group_specs)
|
self.controller.create(req, fake.GROUP_ID, create_fake_group_specs)
|
||||||
self.assertTrue(mock_rpc_notifier.called)
|
self.assertTrue(mock_rpc_notifier.called)
|
||||||
|
|
||||||
@ -108,7 +107,7 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
self.controller.update(req,
|
self.controller.update(req,
|
||||||
fake.GROUP_TYPE_ID,
|
fake.GROUP_TYPE_ID,
|
||||||
'id',
|
'id',
|
||||||
@ -124,7 +123,7 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
res_dict = self.controller.show(req, fake.GROUP_TYPE_ID, 'key1')
|
res_dict = self.controller.show(req, fake.GROUP_TYPE_ID, 'key1')
|
||||||
self.assertEqual('value1', res_dict['key1'])
|
self.assertEqual('value1', res_dict['key1'])
|
||||||
|
|
||||||
@ -138,7 +137,7 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
self.controller.delete(req, fake.GROUP_TYPE_ID, 'key1')
|
self.controller.delete(req, fake.GROUP_TYPE_ID, 'key1')
|
||||||
self.assertTrue(rpc_notifier_mock.called)
|
self.assertTrue(rpc_notifier_mock.called)
|
||||||
|
|
||||||
@ -151,7 +150,7 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
self.assertRaises(webob.exc.HTTPNotFound,
|
self.assertRaises(webob.exc.HTTPNotFound,
|
||||||
self.controller.create,
|
self.controller.create,
|
||||||
req,
|
req,
|
||||||
@ -166,7 +165,7 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
self.assertRaises(webob.exc.HTTPNotFound,
|
self.assertRaises(webob.exc.HTTPNotFound,
|
||||||
self.controller.delete,
|
self.controller.delete,
|
||||||
req,
|
req,
|
||||||
@ -178,7 +177,7 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.update,
|
self.controller.update,
|
||||||
req,
|
req,
|
||||||
@ -198,7 +197,7 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
self.assertRaises(webob.exc.HTTPNotFound,
|
self.assertRaises(webob.exc.HTTPNotFound,
|
||||||
self.controller.show,
|
self.controller.show,
|
||||||
req,
|
req,
|
||||||
@ -216,6 +215,6 @@ class GroupSpecsTestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
req = fakes.HTTPRequest.blank('v3/%s/group_specs' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
||||||
req, fake.GROUP_ID, incorrect_fake_group_specs)
|
req, fake.GROUP_ID, incorrect_fake_group_specs)
|
||||||
|
@ -23,6 +23,7 @@ import six
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
import cinder.api.common as common
|
import cinder.api.common as common
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import group_specs as v3_group_specs
|
from cinder.api.v3 import group_specs as v3_group_specs
|
||||||
from cinder.api.v3 import group_types as v3_group_types
|
from cinder.api.v3 import group_types as v3_group_types
|
||||||
from cinder.api.v3.views import group_types as views_types
|
from cinder.api.v3.views import group_types as views_types
|
||||||
@ -33,7 +34,6 @@ from cinder.tests.unit.api import fakes
|
|||||||
from cinder.tests.unit import fake_constants as fake
|
from cinder.tests.unit import fake_constants as fake
|
||||||
from cinder.volume import group_types
|
from cinder.volume import group_types
|
||||||
|
|
||||||
GROUP_TYPE_MICRO_VERSION = '3.11'
|
|
||||||
IN_USE_GROUP_TYPE = fake.GROUP_TYPE3_ID
|
IN_USE_GROUP_TYPE = fake.GROUP_TYPE3_ID
|
||||||
|
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
mock_create, mock_get):
|
mock_create, mock_get):
|
||||||
boolean_is_public = strutils.bool_from_string(is_public)
|
boolean_is_public = strutils.bool_from_string(is_public)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/types' % fake.PROJECT_ID,
|
req = fakes.HTTPRequest.blank('/v3/%s/types' % fake.PROJECT_ID,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
|
|
||||||
body = {"group_type": {"is_public": is_public, "name": "group_type1",
|
body = {"group_type": {"is_public": is_public, "name": "group_type1",
|
||||||
@ -157,7 +157,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
'_notify_group_type_error')
|
'_notify_group_type_error')
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_types/%s' % (
|
req = fakes.HTTPRequest.blank('/v3/%s/group_types/%s' % (
|
||||||
fake.PROJECT_ID, grp_type_id),
|
fake.PROJECT_ID, grp_type_id),
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
if grp_type_id == IN_USE_GROUP_TYPE:
|
if grp_type_id == IN_USE_GROUP_TYPE:
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
@ -177,7 +177,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
|
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_types' % fake.PROJECT_ID,
|
req = fakes.HTTPRequest.blank('/v3/%s/group_types' % fake.PROJECT_ID,
|
||||||
use_admin_context=True,
|
use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
|
|
||||||
self.assertEqual(3, len(res_dict['group_types']))
|
self.assertEqual(3, len(res_dict['group_types']))
|
||||||
@ -193,7 +193,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
return_empty_group_types_get_all_types)
|
return_empty_group_types_get_all_types)
|
||||||
|
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_types' % fake.PROJECT_ID,
|
req = fakes.HTTPRequest.blank('/v3/%s/group_types' % fake.PROJECT_ID,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
|
|
||||||
self.assertEqual(0, len(res_dict['group_types']))
|
self.assertEqual(0, len(res_dict['group_types']))
|
||||||
@ -201,7 +201,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
def test_group_types_index_with_limit(self):
|
def test_group_types_index_with_limit(self):
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_types?limit=1' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_types?limit=1' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
def test_group_types_index_with_offset(self):
|
def test_group_types_index_with_offset(self):
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/%s/group_types?offset=1' % fake.PROJECT_ID,
|
'/v3/%s/group_types?offset=1' % fake.PROJECT_ID,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
|
|
||||||
@ -224,14 +224,14 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
|
|
||||||
def test_group_types_index_with_offset_out_of_range(self):
|
def test_group_types_index_with_offset_out_of_range(self):
|
||||||
url = '/v3/%s/group_types?offset=424366766556787' % fake.PROJECT_ID
|
url = '/v3/%s/group_types?offset=424366766556787' % fake.PROJECT_ID
|
||||||
req = fakes.HTTPRequest.blank(url, version=GROUP_TYPE_MICRO_VERSION)
|
req = fakes.HTTPRequest.blank(url, version=mv.GROUP_TYPE)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.index, req)
|
self.controller.index, req)
|
||||||
|
|
||||||
def test_group_types_index_with_limit_and_offset(self):
|
def test_group_types_index_with_limit_and_offset(self):
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/%s/group_types?limit=2&offset=1' % fake.PROJECT_ID,
|
'/v3/%s/group_types?limit=2&offset=1' % fake.PROJECT_ID,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
'&marker=%s' %
|
'&marker=%s' %
|
||||||
(fake.PROJECT_ID,
|
(fake.PROJECT_ID,
|
||||||
self.type_id2),
|
self.type_id2),
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
def test_group_types_index_with_valid_filter(self):
|
def test_group_types_index_with_valid_filter(self):
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/%s/group_types?is_public=True' % fake.PROJECT_ID,
|
'/v3/%s/group_types?is_public=True' % fake.PROJECT_ID,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
def test_group_types_index_with_invalid_filter(self):
|
def test_group_types_index_with_invalid_filter(self):
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/%s/group_types?id=%s' % (fake.PROJECT_ID, self.type_id1),
|
'/v3/%s/group_types?id=%s' % (fake.PROJECT_ID, self.type_id1),
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
|
|
||||||
@ -276,7 +276,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
def test_group_types_index_with_sort_keys(self):
|
def test_group_types_index_with_sort_keys(self):
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_types?sort=id' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_types?sort=id' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
expect_result = [self.type_id0, self.type_id1, self.type_id2,
|
expect_result = [self.type_id0, self.type_id1, self.type_id2,
|
||||||
@ -292,7 +292,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
def test_group_types_index_with_sort_and_limit(self):
|
def test_group_types_index_with_sort_and_limit(self):
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/%s/group_types?sort=id&limit=2' % fake.PROJECT_ID,
|
'/v3/%s/group_types?sort=id&limit=2' % fake.PROJECT_ID,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
expect_result = [self.type_id0, self.type_id1, self.type_id2,
|
expect_result = [self.type_id0, self.type_id1, self.type_id2,
|
||||||
@ -306,7 +306,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
def test_group_types_index_with_sort_keys_and_sort_dirs(self):
|
def test_group_types_index_with_sort_keys_and_sort_dirs(self):
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/%s/group_types?sort=id:asc' % fake.PROJECT_ID,
|
'/v3/%s/group_types?sort=id:asc' % fake.PROJECT_ID,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
expect_result = [self.type_id0, self.type_id1, self.type_id2,
|
expect_result = [self.type_id0, self.type_id1, self.type_id2,
|
||||||
@ -332,7 +332,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
type_id = six.text_type(uuid.uuid4())
|
type_id = six.text_type(uuid.uuid4())
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/%s/types/%s' % (fake.PROJECT_ID, type_id),
|
'/v3/%s/types/%s' % (fake.PROJECT_ID, type_id),
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
body = {"group_type": {"is_public": is_public, "name": "group_type1"}}
|
body = {"group_type": {"is_public": is_public, "name": "group_type1"}}
|
||||||
self.controller.update(req, type_id, body)
|
self.controller.update(req, type_id, body)
|
||||||
@ -347,7 +347,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
type_id = six.text_type(uuid.uuid4())
|
type_id = six.text_type(uuid.uuid4())
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_types/' % fake.PROJECT_ID
|
req = fakes.HTTPRequest.blank('/v3/%s/group_types/' % fake.PROJECT_ID
|
||||||
+ type_id,
|
+ type_id,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
res_dict = self.controller.show(req, type_id)
|
res_dict = self.controller.show(req, type_id)
|
||||||
|
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
@ -359,10 +359,10 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
self.mock_object(group_types, 'get_group_type',
|
self.mock_object(group_types, 'get_group_type',
|
||||||
return_group_types_get_group_type)
|
return_group_types_get_group_type)
|
||||||
|
|
||||||
type_id = six.text_type(uuid.uuid4())
|
type_id = uuid.uuid4()
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_types/' % fake.PROJECT_ID
|
req = fakes.HTTPRequest.blank(
|
||||||
+ type_id,
|
'/v3/%s/group_types/%s' % (fake.PROJECT_ID, type_id),
|
||||||
version='3.5')
|
version=mv.get_prior_version(mv.GROUP_TYPE))
|
||||||
|
|
||||||
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
||||||
self.controller.show, req, type_id)
|
self.controller.show, req, type_id)
|
||||||
@ -374,7 +374,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_types/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_types/%s' %
|
||||||
(fake.PROJECT_ID,
|
(fake.PROJECT_ID,
|
||||||
fake.WILL_NOT_BE_FOUND_ID),
|
fake.WILL_NOT_BE_FOUND_ID),
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
|
self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
|
||||||
req, fake.WILL_NOT_BE_FOUND_ID)
|
req, fake.WILL_NOT_BE_FOUND_ID)
|
||||||
|
|
||||||
@ -383,7 +383,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
return_group_types_get_default)
|
return_group_types_get_default)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_types/default' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_types/default' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
res_dict = self.controller.show(req, 'default')
|
res_dict = self.controller.show(req, 'default')
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
@ -396,7 +396,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
return_group_types_get_default_not_found)
|
return_group_types_get_default_not_found)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/group_types/default' %
|
req = fakes.HTTPRequest.blank('/v3/%s/group_types/default' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
|
|
||||||
self.assertRaises(webob.exc.HTTPNotFound,
|
self.assertRaises(webob.exc.HTTPNotFound,
|
||||||
@ -419,7 +419,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
request = fakes.HTTPRequest.blank("/v3",
|
request = fakes.HTTPRequest.blank("/v3",
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
output = view_builder.show(request, raw_group_type)
|
output = view_builder.show(request, raw_group_type)
|
||||||
|
|
||||||
self.assertIn('group_type', output)
|
self.assertIn('group_type', output)
|
||||||
@ -448,7 +448,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
request = fakes.HTTPRequest.blank("/v3", use_admin_context=True,
|
request = fakes.HTTPRequest.blank("/v3", use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
output = view_builder.show(request, raw_group_type)
|
output = view_builder.show(request, raw_group_type)
|
||||||
|
|
||||||
self.assertIn('group_type', output)
|
self.assertIn('group_type', output)
|
||||||
@ -479,7 +479,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
request = fakes.HTTPRequest.blank("/v3",
|
request = fakes.HTTPRequest.blank("/v3",
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
output = view_builder.show(request, raw_group_type)
|
output = view_builder.show(request, raw_group_type)
|
||||||
|
|
||||||
self.assertIn('group_type', output)
|
self.assertIn('group_type', output)
|
||||||
@ -510,7 +510,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
request = fakes.HTTPRequest.blank("/v3",
|
request = fakes.HTTPRequest.blank("/v3",
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
output = view_builder.show(request, raw_group_type)
|
output = view_builder.show(request, raw_group_type)
|
||||||
|
|
||||||
self.assertIn('group_type', output)
|
self.assertIn('group_type', output)
|
||||||
@ -542,7 +542,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
request = fakes.HTTPRequest.blank("/v3",
|
request = fakes.HTTPRequest.blank("/v3",
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
output = view_builder.show(request, raw_group_type)
|
output = view_builder.show(request, raw_group_type)
|
||||||
|
|
||||||
self.assertIn('group_type', output)
|
self.assertIn('group_type', output)
|
||||||
@ -576,7 +576,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
request = fakes.HTTPRequest.blank("/v3",
|
request = fakes.HTTPRequest.blank("/v3",
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
output = view_builder.index(request, raw_group_types)
|
output = view_builder.index(request, raw_group_types)
|
||||||
|
|
||||||
self.assertIn('group_types', output)
|
self.assertIn('group_types', output)
|
||||||
@ -611,7 +611,7 @@ class GroupTypesApiTest(test.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
request = fakes.HTTPRequest.blank("/v3", use_admin_context=True,
|
request = fakes.HTTPRequest.blank("/v3", use_admin_context=True,
|
||||||
version=GROUP_TYPE_MICRO_VERSION)
|
version=mv.GROUP_TYPE)
|
||||||
output = view_builder.index(request, raw_group_types)
|
output = view_builder.index(request, raw_group_types)
|
||||||
|
|
||||||
self.assertIn('group_types', output)
|
self.assertIn('group_types', output)
|
||||||
|
@ -22,6 +22,7 @@ import mock
|
|||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import groups as v3_groups
|
from cinder.api.v3 import groups as v3_groups
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import db
|
from cinder import db
|
||||||
@ -36,10 +37,7 @@ from cinder.tests.unit import fake_constants as fake
|
|||||||
from cinder.tests.unit import utils
|
from cinder.tests.unit import utils
|
||||||
from cinder.volume import api as volume_api
|
from cinder.volume import api as volume_api
|
||||||
|
|
||||||
GROUP_MICRO_VERSION = '3.13'
|
INVALID_GROUP_REPLICATION = mv.get_prior_version(mv.GROUP_REPLICATION)
|
||||||
GROUP_FROM_SRC_MICRO_VERSION = '3.14'
|
|
||||||
GROUP_REPLICATION_MICRO_VERSION = '3.38'
|
|
||||||
INVALID_GROUP_REPLICATION_MICRO_VERSION = '3.37'
|
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
@ -134,7 +132,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
|
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
res_dict = self.controller.show(req, self.group1.id)
|
res_dict = self.controller.show(req, self.group1.id)
|
||||||
|
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
@ -149,7 +147,10 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.assertEqual([fake.VOLUME_TYPE_ID],
|
self.assertEqual([fake.VOLUME_TYPE_ID],
|
||||||
res_dict['group']['volume_types'])
|
res_dict['group']['volume_types'])
|
||||||
|
|
||||||
@ddt.data(('3.24', False), ('3.24', True), ('3.25', False), ('3.25', True))
|
@ddt.data((mv.get_prior_version(mv.GROUP_VOLUME_LIST), False),
|
||||||
|
(mv.get_prior_version(mv.GROUP_VOLUME_LIST), True),
|
||||||
|
(mv.GROUP_VOLUME_LIST, False),
|
||||||
|
(mv.GROUP_VOLUME_LIST, True))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
@mock.patch('cinder.objects.volume_type.VolumeTypeList.get_all_by_group')
|
@mock.patch('cinder.objects.volume_type.VolumeTypeList.get_all_by_group')
|
||||||
@mock.patch('cinder.objects.volume.VolumeList.get_all_by_generic_group')
|
@mock.patch('cinder.objects.volume.VolumeList.get_all_by_generic_group')
|
||||||
@ -178,10 +179,10 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
|
|
||||||
# If the microversion >= 3.25 and "list_volume=True", "volumes" should
|
# If the microversion >= 3.25 and "list_volume=True", "volumes" should
|
||||||
# be contained in the response body. Else,"volumes" should not be
|
# be contained in the response body. Else, "volumes" should not be
|
||||||
# contained in the response body.
|
# contained in the response body.
|
||||||
self.assertEqual(3, len(res_dict['groups']))
|
self.assertEqual(3, len(res_dict['groups']))
|
||||||
if (version, has_list_volume) == ('3.25', True):
|
if (version, has_list_volume) == (mv.GROUP_VOLUME_LIST, True):
|
||||||
self.assertEqual([fake.VOLUME_ID],
|
self.assertEqual([fake.VOLUME_ID],
|
||||||
res_dict['groups'][0]['volumes'])
|
res_dict['groups'][0]['volumes'])
|
||||||
else:
|
else:
|
||||||
@ -211,7 +212,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
# be contained in the response body.
|
# be contained in the response body.
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s?list_volume=True' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s?list_volume=True' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version='3.25')
|
version=mv.GROUP_VOLUME_LIST)
|
||||||
res_dict = self.controller.show(req, self.group1.id)
|
res_dict = self.controller.show(req, self.group1.id)
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
self.assertEqual([fake.VOLUME_ID],
|
self.assertEqual([fake.VOLUME_ID],
|
||||||
@ -221,16 +222,17 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
# should not be contained in the response body.
|
# should not be contained in the response body.
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version='3.25')
|
version=mv.GROUP_VOLUME_LIST)
|
||||||
res_dict = self.controller.show(req, self.group1.id)
|
res_dict = self.controller.show(req, self.group1.id)
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
self.assertIsNone(res_dict['group'].get('volumes', None))
|
self.assertIsNone(res_dict['group'].get('volumes', None))
|
||||||
|
|
||||||
# If the microversion < 3.25, "volumes" should not be contained in the
|
# If the microversion < 3.25, "volumes" should not be contained in the
|
||||||
# response body.
|
# response body.
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s?list_volume=True' %
|
req = fakes.HTTPRequest.blank(
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
'/v3/%s/groups/%s?list_volume=True' %
|
||||||
version='3.24')
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
|
version=mv.get_prior_version(mv.GROUP_VOLUME_LIST))
|
||||||
res_dict = self.controller.show(req, self.group1.id)
|
res_dict = self.controller.show(req, self.group1.id)
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
self.assertIsNone(res_dict['group'].get('volumes', None))
|
self.assertIsNone(res_dict['group'].get('volumes', None))
|
||||||
@ -239,11 +241,12 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s' %
|
||||||
(fake.PROJECT_ID,
|
(fake.PROJECT_ID,
|
||||||
fake.WILL_NOT_BE_FOUND_ID),
|
fake.WILL_NOT_BE_FOUND_ID),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
self.assertRaises(exception.GroupNotFound, self.controller.show,
|
self.assertRaises(exception.GroupNotFound, self.controller.show,
|
||||||
req, fake.WILL_NOT_BE_FOUND_ID)
|
req, fake.WILL_NOT_BE_FOUND_ID)
|
||||||
|
|
||||||
@ddt.data('3.30', '3.31', '3.34')
|
@ddt.data(mv.get_prior_version(mv.RESOURCE_FILTER),
|
||||||
|
mv.RESOURCE_FILTER, mv.LIKE_FILTER)
|
||||||
@mock.patch('cinder.api.common.reject_invalid_filters')
|
@mock.patch('cinder.api.common.reject_invalid_filters')
|
||||||
def test_group_list_with_general_filter(self, version, mock_update):
|
def test_group_list_with_general_filter(self, version, mock_update):
|
||||||
url = '/v3/%s/groups' % fake.PROJECT_ID
|
url = '/v3/%s/groups' % fake.PROJECT_ID
|
||||||
@ -252,8 +255,8 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
use_admin_context=False)
|
use_admin_context=False)
|
||||||
self.controller.index(req)
|
self.controller.index(req)
|
||||||
|
|
||||||
if version != '3.30':
|
if version != mv.get_prior_version(mv.RESOURCE_FILTER):
|
||||||
support_like = True if version == '3.34' else False
|
support_like = True if version == mv.LIKE_FILTER else False
|
||||||
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
||||||
mock.ANY, 'group',
|
mock.ANY, 'group',
|
||||||
support_like)
|
support_like)
|
||||||
@ -273,7 +276,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.group3.save()
|
self.group3.save()
|
||||||
|
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
|
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
@ -295,7 +298,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
url = '/v3/%s/groups?limit=1' % fake.PROJECT_ID
|
url = '/v3/%s/groups?limit=1' % fake.PROJECT_ID
|
||||||
if is_detail:
|
if is_detail:
|
||||||
url = '/v3/%s/groups/detail?limit=1' % fake.PROJECT_ID
|
url = '/v3/%s/groups/detail?limit=1' % fake.PROJECT_ID
|
||||||
req = fakes.HTTPRequest.blank(url, version=GROUP_MICRO_VERSION)
|
req = fakes.HTTPRequest.blank(url, version=mv.GROUP_VOLUME)
|
||||||
|
|
||||||
if is_detail:
|
if is_detail:
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
@ -320,7 +323,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
url = '/v3/%s/groups?offset=1' % fake.PROJECT_ID
|
url = '/v3/%s/groups?offset=1' % fake.PROJECT_ID
|
||||||
if is_detail:
|
if is_detail:
|
||||||
url = '/v3/%s/groups/detail?offset=1' % fake.PROJECT_ID
|
url = '/v3/%s/groups/detail?offset=1' % fake.PROJECT_ID
|
||||||
req = fakes.HTTPRequest.blank(url, version=GROUP_MICRO_VERSION)
|
req = fakes.HTTPRequest.blank(url, version=mv.GROUP_VOLUME)
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
|
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
@ -337,7 +340,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
if is_detail:
|
if is_detail:
|
||||||
url = ('/v3/%s/groups/detail?offset=234523423455454' %
|
url = ('/v3/%s/groups/detail?offset=234523423455454' %
|
||||||
fake.PROJECT_ID)
|
fake.PROJECT_ID)
|
||||||
req = fakes.HTTPRequest.blank(url, version=GROUP_MICRO_VERSION)
|
req = fakes.HTTPRequest.blank(url, version=mv.GROUP_VOLUME)
|
||||||
if is_detail:
|
if is_detail:
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.detail,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.detail,
|
||||||
req)
|
req)
|
||||||
@ -351,7 +354,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
if is_detail:
|
if is_detail:
|
||||||
url = ('/v3/%s/groups/detail?limit=2&offset=1' %
|
url = ('/v3/%s/groups/detail?limit=2&offset=1' %
|
||||||
fake.PROJECT_ID)
|
fake.PROJECT_ID)
|
||||||
req = fakes.HTTPRequest.blank(url, version=GROUP_MICRO_VERSION)
|
req = fakes.HTTPRequest.blank(url, version=mv.GROUP_VOLUME)
|
||||||
|
|
||||||
if is_detail:
|
if is_detail:
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
@ -377,7 +380,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
url = ('/v3/%s/groups/detail?'
|
url = ('/v3/%s/groups/detail?'
|
||||||
'all_tenants=True&id=%s') % (fake.PROJECT_ID,
|
'all_tenants=True&id=%s') % (fake.PROJECT_ID,
|
||||||
self.group3.id)
|
self.group3.id)
|
||||||
req = fakes.HTTPRequest.blank(url, version=GROUP_MICRO_VERSION,
|
req = fakes.HTTPRequest.blank(url, version=mv.GROUP_VOLUME,
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
|
|
||||||
if is_detail:
|
if is_detail:
|
||||||
@ -398,7 +401,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
if is_detail:
|
if is_detail:
|
||||||
url = ('/v3/%s/groups/detail?sort=id:asc' %
|
url = ('/v3/%s/groups/detail?sort=id:asc' %
|
||||||
fake.PROJECT_ID)
|
fake.PROJECT_ID)
|
||||||
req = fakes.HTTPRequest.blank(url, version=GROUP_MICRO_VERSION)
|
req = fakes.HTTPRequest.blank(url, version=mv.GROUP_VOLUME)
|
||||||
expect_result = [self.group1.id, self.group2.id,
|
expect_result = [self.group1.id, self.group2.id,
|
||||||
self.group3.id]
|
self.group3.id]
|
||||||
expect_result.sort()
|
expect_result.sort()
|
||||||
@ -438,7 +441,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
# self.group3.save()
|
# self.group3.save()
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/detail' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/detail' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
|
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
@ -476,7 +479,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
"description":
|
"description":
|
||||||
"Group 1", }}
|
"Group 1", }}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
res_dict = self.controller.create(req, body)
|
res_dict = self.controller.create(req, body)
|
||||||
|
|
||||||
self.assertEqual(1, len(res_dict))
|
self.assertEqual(1, len(res_dict))
|
||||||
@ -489,7 +492,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
def test_create_group_with_no_body(self):
|
def test_create_group_with_no_body(self):
|
||||||
# omit body from the request
|
# omit body from the request
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
||||||
req, None)
|
req, None)
|
||||||
|
|
||||||
@ -498,7 +501,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.group1.save()
|
self.group1.save()
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": False}}
|
body = {"delete": {"delete-volumes": False}}
|
||||||
res_dict = self.controller.delete_group(
|
res_dict = self.controller.delete_group(
|
||||||
req, self.group1.id, body)
|
req, self.group1.id, body)
|
||||||
@ -513,7 +516,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.group1.save()
|
self.group1.save()
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": False}}
|
body = {"delete": {"delete-volumes": False}}
|
||||||
res_dict = self.controller.delete_group(
|
res_dict = self.controller.delete_group(
|
||||||
req, self.group1.id, body)
|
req, self.group1.id, body)
|
||||||
@ -528,7 +531,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID,
|
(fake.PROJECT_ID,
|
||||||
fake.WILL_NOT_BE_FOUND_ID),
|
fake.WILL_NOT_BE_FOUND_ID),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": False}}
|
body = {"delete": {"delete-volumes": False}}
|
||||||
self.assertRaises(exception.GroupNotFound,
|
self.assertRaises(exception.GroupNotFound,
|
||||||
self.controller.delete_group,
|
self.controller.delete_group,
|
||||||
@ -538,7 +541,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID,
|
(fake.PROJECT_ID,
|
||||||
self.group1.id),
|
self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": False}}
|
body = {"delete": {"delete-volumes": False}}
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.delete_group,
|
self.controller.delete_group,
|
||||||
@ -548,7 +551,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID,
|
(fake.PROJECT_ID,
|
||||||
self.group1.id),
|
self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": True}}
|
body = {"delete": {"delete-volumes": True}}
|
||||||
res_dict = self.controller.delete_group(
|
res_dict = self.controller.delete_group(
|
||||||
req, self.group1.id, body)
|
req, self.group1.id, body)
|
||||||
@ -565,7 +568,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID,
|
(fake.PROJECT_ID,
|
||||||
self.group1.id),
|
self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": True}}
|
body = {"delete": {"delete-volumes": True}}
|
||||||
res_dict = self.controller.delete_group(
|
res_dict = self.controller.delete_group(
|
||||||
req, self.group1.id, body)
|
req, self.group1.id, body)
|
||||||
@ -620,7 +623,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
"description":
|
"description":
|
||||||
"Group 1", }}
|
"Group 1", }}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
ex = self.assertRaises(exception.GroupLimitExceeded,
|
ex = self.assertRaises(exception.GroupLimitExceeded,
|
||||||
self.controller.create,
|
self.controller.create,
|
||||||
req, body)
|
req, body)
|
||||||
@ -631,7 +634,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.group1.save()
|
self.group1.save()
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"invalid_request_element": {"delete-volumes": False}}
|
body = {"invalid_request_element": {"delete-volumes": False}}
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.delete_group,
|
self.controller.delete_group,
|
||||||
@ -642,7 +645,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.group1.save()
|
self.group1.save()
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": "abcd"}}
|
body = {"delete": {"delete-volumes": "abcd"}}
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.delete_group,
|
self.controller.delete_group,
|
||||||
@ -653,7 +656,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.group1.save()
|
self.group1.save()
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": ""}}
|
body = {"delete": {"delete-volumes": ""}}
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.delete_group,
|
self.controller.delete_group,
|
||||||
@ -666,7 +669,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
|
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": True}}
|
body = {"delete": {"delete-volumes": True}}
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.delete_group,
|
self.controller.delete_group,
|
||||||
@ -688,7 +691,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
vol = utils.create_volume(self.ctxt, group_id=self.group1.id)
|
vol = utils.create_volume(self.ctxt, group_id=self.group1.id)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": True}}
|
body = {"delete": {"delete-volumes": True}}
|
||||||
res_dict = self.controller.delete_group(
|
res_dict = self.controller.delete_group(
|
||||||
req, self.group1.id, body)
|
req, self.group1.id, body)
|
||||||
@ -707,7 +710,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
attach_status='attached')
|
attach_status='attached')
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": True}}
|
body = {"delete": {"delete-volumes": True}}
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.delete_group,
|
self.controller.delete_group,
|
||||||
@ -722,7 +725,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
utils.create_snapshot(self.ctxt, vol.id)
|
utils.create_snapshot(self.ctxt, vol.id)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": True}}
|
body = {"delete": {"delete-volumes": True}}
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.delete_group,
|
self.controller.delete_group,
|
||||||
@ -739,7 +742,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
deleted=True)
|
deleted=True)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"delete": {"delete-volumes": True}}
|
body = {"delete": {"delete-volumes": True}}
|
||||||
res_dict = self.controller.delete_group(
|
res_dict = self.controller.delete_group(
|
||||||
req, self.group1.id, body)
|
req, self.group1.id, body)
|
||||||
@ -758,7 +761,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
"description":
|
"description":
|
||||||
"Group 1", }}
|
"Group 1", }}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.create,
|
self.controller.create,
|
||||||
req, body)
|
req, body)
|
||||||
@ -770,7 +773,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
"description":
|
"description":
|
||||||
"Group 1", }}
|
"Group 1", }}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
req = fakes.HTTPRequest.blank('/v3/%s/groups' % fake.PROJECT_ID,
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.create,
|
self.controller.create,
|
||||||
req, body)
|
req, body)
|
||||||
@ -820,7 +823,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
volume_type_id=volume_type_id)
|
volume_type_id=volume_type_id)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
name = 'newgroup'
|
name = 'newgroup'
|
||||||
description = 'New Group Description'
|
description = 'New Group Description'
|
||||||
add_volumes = add_volume.id + "," + add_volume2.id
|
add_volumes = add_volume.id + "," + add_volume2.id
|
||||||
@ -851,7 +854,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.group1.status = status
|
self.group1.status = status
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"group": {"name": "new name",
|
body = {"group": {"name": "new name",
|
||||||
"description": "new description",
|
"description": "new description",
|
||||||
"add_volumes": None,
|
"add_volumes": None,
|
||||||
@ -870,7 +873,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.group1.save()
|
self.group1.save()
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"group": {"name": None,
|
body = {"group": {"name": None,
|
||||||
"description": None,
|
"description": None,
|
||||||
"add_volumes": "fake-volume-uuid",
|
"add_volumes": "fake-volume-uuid",
|
||||||
@ -885,7 +888,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.group1.save()
|
self.group1.save()
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"group": {"name": None,
|
body = {"group": {"name": None,
|
||||||
"description": "new description",
|
"description": "new description",
|
||||||
"add_volumes": None,
|
"add_volumes": None,
|
||||||
@ -900,7 +903,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.group1.save()
|
self.group1.save()
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
body = {"group": {"name": None,
|
body = {"group": {"name": None,
|
||||||
"description": None,
|
"description": None,
|
||||||
"add_volumes": None,
|
"add_volumes": None,
|
||||||
@ -919,7 +922,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
status='wrong_status')
|
status='wrong_status')
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
add_volumes = add_volume.id
|
add_volumes = add_volume.id
|
||||||
body = {"group": {"name": "group1",
|
body = {"group": {"name": "group1",
|
||||||
"description": "",
|
"description": "",
|
||||||
@ -941,7 +944,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
volume_type_id=wrong_type)
|
volume_type_id=wrong_type)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
add_volumes = add_volume.id
|
add_volumes = add_volume.id
|
||||||
body = {"group": {"name": "group1",
|
body = {"group": {"name": "group1",
|
||||||
"description": "",
|
"description": "",
|
||||||
@ -962,7 +965,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
group_id=fake.GROUP2_ID)
|
group_id=fake.GROUP2_ID)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
add_volumes = add_volume.id
|
add_volumes = add_volume.id
|
||||||
body = {"group": {"name": "group1",
|
body = {"group": {"name": "group1",
|
||||||
"description": "",
|
"description": "",
|
||||||
@ -984,7 +987,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
host=self.group1.host)
|
host=self.group1.host)
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/update' %
|
||||||
(fake.PROJECT_ID, self.group1.id),
|
(fake.PROJECT_ID, self.group1.id),
|
||||||
version=GROUP_MICRO_VERSION)
|
version=mv.GROUP_VOLUME)
|
||||||
|
|
||||||
body = {"group": {"name": "new name",
|
body = {"group": {"name": "new name",
|
||||||
"description": None,
|
"description": None,
|
||||||
@ -999,16 +1002,16 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
self.assertEqual(add_volume.status, vol.status)
|
self.assertEqual(add_volume.status, vol.status)
|
||||||
add_volume.destroy()
|
add_volume.destroy()
|
||||||
|
|
||||||
@ddt.data(('3.11', 'fake_group_001',
|
@ddt.data((mv.GROUP_TYPE, 'fake_group_001',
|
||||||
fields.GroupStatus.AVAILABLE,
|
fields.GroupStatus.AVAILABLE,
|
||||||
exception.VersionNotFoundForAPIMethod),
|
exception.VersionNotFoundForAPIMethod),
|
||||||
('3.19', 'fake_group_001',
|
(mv.GROUP_SNAPSHOT_RESET_STATUS, 'fake_group_001',
|
||||||
fields.GroupStatus.AVAILABLE,
|
fields.GroupStatus.AVAILABLE,
|
||||||
exception.VersionNotFoundForAPIMethod),
|
exception.VersionNotFoundForAPIMethod),
|
||||||
('3.20', 'fake_group_001',
|
(mv.GROUP_VOLUME_RESET_STATUS, 'fake_group_001',
|
||||||
fields.GroupStatus.AVAILABLE,
|
fields.GroupStatus.AVAILABLE,
|
||||||
exception.GroupNotFound),
|
exception.GroupNotFound),
|
||||||
('3.20', None,
|
(mv.GROUP_VOLUME_RESET_STATUS, None,
|
||||||
'invalid_test_status',
|
'invalid_test_status',
|
||||||
webob.exc.HTTPBadRequest),
|
webob.exc.HTTPBadRequest),
|
||||||
)
|
)
|
||||||
@ -1029,7 +1032,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
def test_reset_group_status(self):
|
def test_reset_group_status(self):
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group2.id),
|
(fake.PROJECT_ID, self.group2.id),
|
||||||
version='3.20')
|
version=mv.GROUP_VOLUME_RESET_STATUS)
|
||||||
body = {"reset_status": {
|
body = {"reset_status": {
|
||||||
"status": fields.GroupStatus.AVAILABLE
|
"status": fields.GroupStatus.AVAILABLE
|
||||||
}}
|
}}
|
||||||
@ -1068,7 +1071,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
"group_snapshot_id": group_snapshot.id}}
|
"group_snapshot_id": group_snapshot.id}}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/action' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_FROM_SRC_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
res_dict = self.controller.create_from_src(req, body)
|
res_dict = self.controller.create_from_src(req, body)
|
||||||
|
|
||||||
self.assertIn('id', res_dict['group'])
|
self.assertIn('id', res_dict['group'])
|
||||||
@ -1101,7 +1104,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
"source_group_id": source_grp.id}}
|
"source_group_id": source_grp.id}}
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/action' %
|
||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
version=GROUP_FROM_SRC_MICRO_VERSION)
|
version=mv.GROUP_SNAPSHOTS)
|
||||||
res_dict = self.controller.create_from_src(req, body)
|
res_dict = self.controller.create_from_src(req, body)
|
||||||
|
|
||||||
self.assertIn('id', res_dict['group'])
|
self.assertIn('id', res_dict['group'])
|
||||||
@ -1120,7 +1123,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
def test_enable_replication(self, mock_rep_grp_type, mock_rep_vol_type):
|
def test_enable_replication(self, mock_rep_grp_type, mock_rep_vol_type):
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group3.id),
|
(fake.PROJECT_ID, self.group3.id),
|
||||||
version=GROUP_REPLICATION_MICRO_VERSION)
|
version=mv.GROUP_REPLICATION)
|
||||||
self.group3.status = fields.GroupStatus.AVAILABLE
|
self.group3.status = fields.GroupStatus.AVAILABLE
|
||||||
self.group3.save()
|
self.group3.save()
|
||||||
body = {"enable_replication": {}}
|
body = {"enable_replication": {}}
|
||||||
@ -1145,7 +1148,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
mock_rep_vol_type.return_value = is_vol_rep_type
|
mock_rep_vol_type.return_value = is_vol_rep_type
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group3.id),
|
(fake.PROJECT_ID, self.group3.id),
|
||||||
version=GROUP_REPLICATION_MICRO_VERSION)
|
version=mv.GROUP_REPLICATION)
|
||||||
self.group3.status = fields.GroupStatus.AVAILABLE
|
self.group3.status = fields.GroupStatus.AVAILABLE
|
||||||
self.group3.save()
|
self.group3.save()
|
||||||
body = {"enable_replication": {}}
|
body = {"enable_replication": {}}
|
||||||
@ -1161,7 +1164,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
mock_rep_vol_type):
|
mock_rep_vol_type):
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group3.id),
|
(fake.PROJECT_ID, self.group3.id),
|
||||||
version=GROUP_REPLICATION_MICRO_VERSION)
|
version=mv.GROUP_REPLICATION)
|
||||||
self.group3.status = fields.GroupStatus.AVAILABLE
|
self.group3.status = fields.GroupStatus.AVAILABLE
|
||||||
self.group3.save()
|
self.group3.save()
|
||||||
body = {"enable_replication": {}}
|
body = {"enable_replication": {}}
|
||||||
@ -1173,13 +1176,13 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
return_value=True)
|
return_value=True)
|
||||||
@mock.patch('cinder.volume.utils.is_group_a_type',
|
@mock.patch('cinder.volume.utils.is_group_a_type',
|
||||||
return_value=True)
|
return_value=True)
|
||||||
@ddt.data((GROUP_REPLICATION_MICRO_VERSION, True,
|
@ddt.data((mv.GROUP_REPLICATION, True,
|
||||||
fields.GroupStatus.CREATING,
|
fields.GroupStatus.CREATING,
|
||||||
webob.exc.HTTPBadRequest),
|
webob.exc.HTTPBadRequest),
|
||||||
(GROUP_REPLICATION_MICRO_VERSION, False,
|
(mv.GROUP_REPLICATION, False,
|
||||||
fields.GroupStatus.AVAILABLE,
|
fields.GroupStatus.AVAILABLE,
|
||||||
exception.GroupNotFound),
|
exception.GroupNotFound),
|
||||||
(INVALID_GROUP_REPLICATION_MICRO_VERSION, True,
|
(INVALID_GROUP_REPLICATION, True,
|
||||||
fields.GroupStatus.AVAILABLE,
|
fields.GroupStatus.AVAILABLE,
|
||||||
exception.VersionNotFoundForAPIMethod),
|
exception.VersionNotFoundForAPIMethod),
|
||||||
)
|
)
|
||||||
@ -1209,7 +1212,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
def test_disable_replication(self, mock_rep_grp_type, mock_rep_vol_type):
|
def test_disable_replication(self, mock_rep_grp_type, mock_rep_vol_type):
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group3.id),
|
(fake.PROJECT_ID, self.group3.id),
|
||||||
version=GROUP_REPLICATION_MICRO_VERSION)
|
version=mv.GROUP_REPLICATION)
|
||||||
self.group3.status = fields.GroupStatus.AVAILABLE
|
self.group3.status = fields.GroupStatus.AVAILABLE
|
||||||
self.group3.replication_status = fields.ReplicationStatus.ENABLED
|
self.group3.replication_status = fields.ReplicationStatus.ENABLED
|
||||||
self.group3.save()
|
self.group3.save()
|
||||||
@ -1227,19 +1230,19 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
return_value=True)
|
return_value=True)
|
||||||
@mock.patch('cinder.volume.utils.is_group_a_type',
|
@mock.patch('cinder.volume.utils.is_group_a_type',
|
||||||
return_value=True)
|
return_value=True)
|
||||||
@ddt.data((GROUP_REPLICATION_MICRO_VERSION, True,
|
@ddt.data((mv.GROUP_REPLICATION, True,
|
||||||
fields.GroupStatus.CREATING,
|
fields.GroupStatus.CREATING,
|
||||||
fields.ReplicationStatus.ENABLED,
|
fields.ReplicationStatus.ENABLED,
|
||||||
webob.exc.HTTPBadRequest),
|
webob.exc.HTTPBadRequest),
|
||||||
(GROUP_REPLICATION_MICRO_VERSION, True,
|
(mv.GROUP_REPLICATION, True,
|
||||||
fields.GroupStatus.AVAILABLE,
|
fields.GroupStatus.AVAILABLE,
|
||||||
fields.ReplicationStatus.DISABLED,
|
fields.ReplicationStatus.DISABLED,
|
||||||
webob.exc.HTTPBadRequest),
|
webob.exc.HTTPBadRequest),
|
||||||
(GROUP_REPLICATION_MICRO_VERSION, False,
|
(mv.GROUP_REPLICATION, False,
|
||||||
fields.GroupStatus.AVAILABLE,
|
fields.GroupStatus.AVAILABLE,
|
||||||
fields.ReplicationStatus.DISABLED,
|
fields.ReplicationStatus.DISABLED,
|
||||||
exception.GroupNotFound),
|
exception.GroupNotFound),
|
||||||
(INVALID_GROUP_REPLICATION_MICRO_VERSION, True,
|
(INVALID_GROUP_REPLICATION, True,
|
||||||
fields.GroupStatus.AVAILABLE,
|
fields.GroupStatus.AVAILABLE,
|
||||||
fields.ReplicationStatus.ENABLED,
|
fields.ReplicationStatus.ENABLED,
|
||||||
exception.VersionNotFoundForAPIMethod),
|
exception.VersionNotFoundForAPIMethod),
|
||||||
@ -1272,7 +1275,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
def test_failover_replication(self, mock_rep_grp_type, mock_rep_vol_type):
|
def test_failover_replication(self, mock_rep_grp_type, mock_rep_vol_type):
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group3.id),
|
(fake.PROJECT_ID, self.group3.id),
|
||||||
version=GROUP_REPLICATION_MICRO_VERSION)
|
version=mv.GROUP_REPLICATION)
|
||||||
self.group3.status = fields.GroupStatus.AVAILABLE
|
self.group3.status = fields.GroupStatus.AVAILABLE
|
||||||
self.group3.replication_status = fields.ReplicationStatus.ENABLED
|
self.group3.replication_status = fields.ReplicationStatus.ENABLED
|
||||||
self.group3.save()
|
self.group3.save()
|
||||||
@ -1290,19 +1293,19 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
return_value=True)
|
return_value=True)
|
||||||
@mock.patch('cinder.volume.utils.is_group_a_type',
|
@mock.patch('cinder.volume.utils.is_group_a_type',
|
||||||
return_value=True)
|
return_value=True)
|
||||||
@ddt.data((GROUP_REPLICATION_MICRO_VERSION, True,
|
@ddt.data((mv.GROUP_REPLICATION, True,
|
||||||
fields.GroupStatus.CREATING,
|
fields.GroupStatus.CREATING,
|
||||||
fields.ReplicationStatus.ENABLED,
|
fields.ReplicationStatus.ENABLED,
|
||||||
webob.exc.HTTPBadRequest),
|
webob.exc.HTTPBadRequest),
|
||||||
(GROUP_REPLICATION_MICRO_VERSION, True,
|
(mv.GROUP_REPLICATION, True,
|
||||||
fields.GroupStatus.AVAILABLE,
|
fields.GroupStatus.AVAILABLE,
|
||||||
fields.ReplicationStatus.DISABLED,
|
fields.ReplicationStatus.DISABLED,
|
||||||
webob.exc.HTTPBadRequest),
|
webob.exc.HTTPBadRequest),
|
||||||
(GROUP_REPLICATION_MICRO_VERSION, False,
|
(mv.GROUP_REPLICATION, False,
|
||||||
fields.GroupStatus.AVAILABLE,
|
fields.GroupStatus.AVAILABLE,
|
||||||
fields.ReplicationStatus.DISABLED,
|
fields.ReplicationStatus.DISABLED,
|
||||||
exception.GroupNotFound),
|
exception.GroupNotFound),
|
||||||
(INVALID_GROUP_REPLICATION_MICRO_VERSION, True,
|
(INVALID_GROUP_REPLICATION, True,
|
||||||
fields.GroupStatus.AVAILABLE,
|
fields.GroupStatus.AVAILABLE,
|
||||||
fields.ReplicationStatus.ENABLED,
|
fields.ReplicationStatus.ENABLED,
|
||||||
exception.VersionNotFoundForAPIMethod),
|
exception.VersionNotFoundForAPIMethod),
|
||||||
@ -1337,7 +1340,7 @@ class GroupsAPITestCase(test.TestCase):
|
|||||||
mock_rep_grp_type, mock_rep_vol_type):
|
mock_rep_grp_type, mock_rep_vol_type):
|
||||||
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' %
|
||||||
(fake.PROJECT_ID, self.group3.id),
|
(fake.PROJECT_ID, self.group3.id),
|
||||||
version=GROUP_REPLICATION_MICRO_VERSION)
|
version=mv.GROUP_REPLICATION)
|
||||||
targets = {
|
targets = {
|
||||||
'replication_targets': [
|
'replication_targets': [
|
||||||
{'backend_id': 'lvm_backend_1'}
|
{'backend_id': 'lvm_backend_1'}
|
||||||
|
@ -16,12 +16,16 @@
|
|||||||
import ddt
|
import ddt
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api.openstack import api_version_request as api_version
|
||||||
from cinder.api.v3 import limits
|
from cinder.api.v3 import limits
|
||||||
from cinder import test
|
from cinder import test
|
||||||
from cinder.tests.unit.api import fakes
|
from cinder.tests.unit.api import fakes
|
||||||
from cinder.tests.unit import fake_constants as fake
|
from cinder.tests.unit import fake_constants as fake
|
||||||
|
|
||||||
|
LIMITS_FILTER = mv.LIMITS_ADMIN_FILTER
|
||||||
|
PRE_LIMITS_FILTER = mv.get_prior_version(LIMITS_FILTER)
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class LimitsControllerTest(test.TestCase):
|
class LimitsControllerTest(test.TestCase):
|
||||||
@ -29,7 +33,8 @@ class LimitsControllerTest(test.TestCase):
|
|||||||
super(LimitsControllerTest, self).setUp()
|
super(LimitsControllerTest, self).setUp()
|
||||||
self.controller = limits.LimitsController()
|
self.controller = limits.LimitsController()
|
||||||
|
|
||||||
@ddt.data(('3.38', True), ('3.38', False), ('3.39', True), ('3.39', False))
|
@ddt.data((PRE_LIMITS_FILTER, True), (PRE_LIMITS_FILTER, False),
|
||||||
|
(LIMITS_FILTER, True), (LIMITS_FILTER, False))
|
||||||
@mock.patch('cinder.quota.VolumeTypeQuotaEngine.get_project_quotas')
|
@mock.patch('cinder.quota.VolumeTypeQuotaEngine.get_project_quotas')
|
||||||
def test_get_limit_with_project_id(self, ver_project, mock_get_quotas):
|
def test_get_limit_with_project_id(self, ver_project, mock_get_quotas):
|
||||||
max_ver, has_project = ver_project
|
max_ver, has_project = ver_project
|
||||||
@ -48,9 +53,9 @@ class LimitsControllerTest(test.TestCase):
|
|||||||
mock_get_quotas.side_effect = get_project_quotas
|
mock_get_quotas.side_effect = get_project_quotas
|
||||||
|
|
||||||
resp_dict = self.controller.index(req)
|
resp_dict = self.controller.index(req)
|
||||||
# if admin, only 3.39 and req contains project_id filter, cinder
|
# if admin, only LIMITS_FILTER and req contains project_id filter,
|
||||||
# returns the specified project's quota.
|
# cinder returns the specified project's quota.
|
||||||
if max_ver == '3.39' and has_project:
|
if max_ver == LIMITS_FILTER and has_project:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
5, resp_dict['limits']['absolute']['maxTotalVolumeGigabytes'])
|
5, resp_dict['limits']['absolute']['maxTotalVolumeGigabytes'])
|
||||||
else:
|
else:
|
||||||
|
@ -15,6 +15,7 @@ import mock
|
|||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
|
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import messages
|
from cinder.api.v3 import messages
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -66,8 +67,7 @@ class MessageApiTest(test.TestCase):
|
|||||||
self.mock_object(message_api.API, 'get', v3_fakes.fake_message_get)
|
self.mock_object(message_api.API, 'get', v3_fakes.fake_message_get)
|
||||||
|
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/messages/%s' % fakes.FAKE_UUID,
|
'/v3/messages/%s' % fakes.FAKE_UUID, version=mv.MESSAGES)
|
||||||
version=messages.MESSAGES_BASE_MICRO_VERSION)
|
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
|
|
||||||
res_dict = self.controller.show(req, fakes.FAKE_UUID)
|
res_dict = self.controller.show(req, fakes.FAKE_UUID)
|
||||||
@ -81,8 +81,7 @@ class MessageApiTest(test.TestCase):
|
|||||||
message_id=fakes.FAKE_UUID))
|
message_id=fakes.FAKE_UUID))
|
||||||
|
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/messages/%s' % fakes.FAKE_UUID,
|
'/v3/messages/%s' % fakes.FAKE_UUID, version=mv.MESSAGES)
|
||||||
version=messages.MESSAGES_BASE_MICRO_VERSION)
|
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
|
|
||||||
self.assertRaises(exception.MessageNotFound, self.controller.show,
|
self.assertRaises(exception.MessageNotFound, self.controller.show,
|
||||||
@ -92,7 +91,7 @@ class MessageApiTest(test.TestCase):
|
|||||||
self.mock_object(message_api.API, 'get', v3_fakes.fake_message_get)
|
self.mock_object(message_api.API, 'get', v3_fakes.fake_message_get)
|
||||||
|
|
||||||
req = fakes.HTTPRequest.blank('/v3/messages/%s' % fakes.FAKE_UUID,
|
req = fakes.HTTPRequest.blank('/v3/messages/%s' % fakes.FAKE_UUID,
|
||||||
version='3.0')
|
version=mv.BASE_VERSION)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
|
|
||||||
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
||||||
@ -103,8 +102,7 @@ class MessageApiTest(test.TestCase):
|
|||||||
self.mock_object(message_api.API, 'delete')
|
self.mock_object(message_api.API, 'delete')
|
||||||
|
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/messages/%s' % fakes.FAKE_UUID,
|
'/v3/messages/%s' % fakes.FAKE_UUID, version=mv.MESSAGES)
|
||||||
version=messages.MESSAGES_BASE_MICRO_VERSION)
|
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
|
|
||||||
resp = self.controller.delete(req, fakes.FAKE_UUID)
|
resp = self.controller.delete(req, fakes.FAKE_UUID)
|
||||||
@ -118,13 +116,13 @@ class MessageApiTest(test.TestCase):
|
|||||||
message_id=fakes.FAKE_UUID))
|
message_id=fakes.FAKE_UUID))
|
||||||
|
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/messages/%s' % fakes.FAKE_UUID,
|
'/v3/messages/%s' % fakes.FAKE_UUID, version=mv.MESSAGES)
|
||||||
version=messages.MESSAGES_BASE_MICRO_VERSION)
|
|
||||||
|
|
||||||
self.assertRaises(exception.MessageNotFound, self.controller.delete,
|
self.assertRaises(exception.MessageNotFound, self.controller.delete,
|
||||||
req, fakes.FAKE_UUID)
|
req, fakes.FAKE_UUID)
|
||||||
|
|
||||||
@ddt.data('3.30', '3.31', '3.34')
|
@ddt.data(mv.get_prior_version(mv.RESOURCE_FILTER),
|
||||||
|
mv.RESOURCE_FILTER, mv.LIKE_FILTER)
|
||||||
@mock.patch('cinder.api.common.reject_invalid_filters')
|
@mock.patch('cinder.api.common.reject_invalid_filters')
|
||||||
def test_message_list_with_general_filter(self, version, mock_update):
|
def test_message_list_with_general_filter(self, version, mock_update):
|
||||||
url = '/v3/%s/messages' % fakes.FAKE_UUID
|
url = '/v3/%s/messages' % fakes.FAKE_UUID
|
||||||
@ -133,8 +131,8 @@ class MessageApiTest(test.TestCase):
|
|||||||
use_admin_context=False)
|
use_admin_context=False)
|
||||||
self.controller.index(req)
|
self.controller.index(req)
|
||||||
|
|
||||||
if version != '3.30':
|
if version != mv.get_prior_version(mv.RESOURCE_FILTER):
|
||||||
support_like = True if version == '3.34' else False
|
support_like = True if version == mv.LIKE_FILTER else False
|
||||||
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
||||||
mock.ANY, 'message',
|
mock.ANY, 'message',
|
||||||
support_like)
|
support_like)
|
||||||
@ -143,8 +141,7 @@ class MessageApiTest(test.TestCase):
|
|||||||
self.mock_object(message_api.API, 'get_all',
|
self.mock_object(message_api.API, 'get_all',
|
||||||
return_value=[v3_fakes.fake_message(fakes.FAKE_UUID)])
|
return_value=[v3_fakes.fake_message(fakes.FAKE_UUID)])
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v3/messages/%s' % fakes.FAKE_UUID,
|
'/v3/messages/%s' % fakes.FAKE_UUID, version=mv.MESSAGES)
|
||||||
version=messages.MESSAGES_BASE_MICRO_VERSION)
|
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
|
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
|
@ -18,13 +18,12 @@ import ddt
|
|||||||
import mock
|
import mock
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import resource_filters as v3_filters
|
from cinder.api.v3 import resource_filters as v3_filters
|
||||||
from cinder import test
|
from cinder import test
|
||||||
from cinder.tests.unit.api import fakes
|
from cinder.tests.unit.api import fakes
|
||||||
from cinder.tests.unit import fake_constants as fake
|
from cinder.tests.unit import fake_constants as fake
|
||||||
|
|
||||||
FILTERS_MICRO_VERSION = '3.33'
|
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class ResourceFiltersAPITestCase(test.TestCase):
|
class ResourceFiltersAPITestCase(test.TestCase):
|
||||||
@ -53,7 +52,7 @@ class ResourceFiltersAPITestCase(test.TestCase):
|
|||||||
if resource is not None:
|
if resource is not None:
|
||||||
request_url += '?resource=%s' % resource
|
request_url += '?resource=%s' % resource
|
||||||
req = fakes.HTTPRequest.blank(request_url,
|
req = fakes.HTTPRequest.blank(request_url,
|
||||||
version=FILTERS_MICRO_VERSION)
|
version=mv.RESOURCE_FILTER_CONFIG)
|
||||||
|
|
||||||
with mock.patch('cinder.api.common._FILTERS_COLLECTION', filters):
|
with mock.patch('cinder.api.common._FILTERS_COLLECTION', filters):
|
||||||
result = self.controller.index(req)
|
result = self.controller.index(req)
|
||||||
|
@ -20,6 +20,7 @@ from six.moves import http_client
|
|||||||
from six.moves.urllib.parse import urlencode
|
from six.moves.urllib.parse import urlencode
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import router as router_v3
|
from cinder.api.v3 import router as router_v3
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import objects
|
from cinder import objects
|
||||||
@ -51,13 +52,13 @@ class SnapshotManageTest(test.TestCase):
|
|||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
True)
|
True)
|
||||||
|
|
||||||
def _get_resp_post(self, body, version="3.8"):
|
def _get_resp_post(self, body, version=mv.MANAGE_EXISTING_LIST):
|
||||||
"""Helper to execute a POST manageable_snapshots API call."""
|
"""Helper to execute a POST manageable_snapshots API call."""
|
||||||
req = webob.Request.blank('/v3/%s/manageable_snapshots' %
|
req = webob.Request.blank('/v3/%s/manageable_snapshots' %
|
||||||
fake.PROJECT_ID)
|
fake.PROJECT_ID)
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
|
req.headers = mv.get_mv_header(version)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume ' + version
|
|
||||||
req.environ['cinder.context'] = self._admin_ctxt
|
req.environ['cinder.context'] = self._admin_ctxt
|
||||||
req.body = jsonutils.dump_as_bytes(body)
|
req.body = jsonutils.dump_as_bytes(body)
|
||||||
res = req.get_response(app())
|
res = req.get_response(app())
|
||||||
@ -84,10 +85,12 @@ class SnapshotManageTest(test.TestCase):
|
|||||||
|
|
||||||
def test_manage_snapshot_previous_version(self):
|
def test_manage_snapshot_previous_version(self):
|
||||||
body = {'snapshot': {'volume_id': fake.VOLUME_ID, 'ref': 'fake_ref'}}
|
body = {'snapshot': {'volume_id': fake.VOLUME_ID, 'ref': 'fake_ref'}}
|
||||||
res = self._get_resp_post(body, version="3.7")
|
res = self._get_resp_post(
|
||||||
|
body, version=mv.get_prior_version(mv.MANAGE_EXISTING_LIST))
|
||||||
self.assertEqual(http_client.NOT_FOUND, res.status_int, res)
|
self.assertEqual(http_client.NOT_FOUND, res.status_int, res)
|
||||||
|
|
||||||
def _get_resp_get(self, host, detailed, paging, version="3.8", **kwargs):
|
def _get_resp_get(self, host, detailed, paging,
|
||||||
|
version=mv.MANAGE_EXISTING_LIST, **kwargs):
|
||||||
"""Helper to execute a GET os-snapshot-manage API call."""
|
"""Helper to execute a GET os-snapshot-manage API call."""
|
||||||
params = {'host': host} if host else {}
|
params = {'host': host} if host else {}
|
||||||
params.update(kwargs)
|
params.update(kwargs)
|
||||||
@ -101,8 +104,8 @@ class SnapshotManageTest(test.TestCase):
|
|||||||
req = webob.Request.blank('/v3/%s/manageable_snapshots%s%s' %
|
req = webob.Request.blank('/v3/%s/manageable_snapshots%s%s' %
|
||||||
(fake.PROJECT_ID, detail, query_string))
|
(fake.PROJECT_ID, detail, query_string))
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
|
req.headers = mv.get_mv_header(version)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume ' + version
|
|
||||||
req.environ['cinder.context'] = self._admin_ctxt
|
req.environ['cinder.context'] = self._admin_ctxt
|
||||||
res = req.get_response(app())
|
res = req.get_response(app())
|
||||||
return res
|
return res
|
||||||
@ -120,7 +123,9 @@ class SnapshotManageTest(test.TestCase):
|
|||||||
self.assertEqual(http_client.OK, res.status_int)
|
self.assertEqual(http_client.OK, res.status_int)
|
||||||
|
|
||||||
def test_get_manageable_snapshots_previous_version(self):
|
def test_get_manageable_snapshots_previous_version(self):
|
||||||
res = self._get_resp_get('fakehost', False, False, version="3.7")
|
res = self._get_resp_get(
|
||||||
|
'fakehost', False, False,
|
||||||
|
version=mv.get_prior_version(mv.MANAGE_EXISTING_LIST))
|
||||||
self.assertEqual(http_client.NOT_FOUND, res.status_int)
|
self.assertEqual(http_client.NOT_FOUND, res.status_int)
|
||||||
|
|
||||||
@mock.patch('cinder.volume.api.API.get_manageable_snapshots',
|
@mock.patch('cinder.volume.api.API.get_manageable_snapshots',
|
||||||
@ -136,7 +141,9 @@ class SnapshotManageTest(test.TestCase):
|
|||||||
self.assertEqual(http_client.OK, res.status_int)
|
self.assertEqual(http_client.OK, res.status_int)
|
||||||
|
|
||||||
def test_get_manageable_snapshots_detail_previous_version(self):
|
def test_get_manageable_snapshots_detail_previous_version(self):
|
||||||
res = self._get_resp_get('fakehost', True, True, version="3.7")
|
res = self._get_resp_get(
|
||||||
|
'fakehost', True, True,
|
||||||
|
version=mv.get_prior_version(mv.MANAGE_EXISTING_LIST))
|
||||||
self.assertEqual(http_client.NOT_FOUND, res.status_int)
|
self.assertEqual(http_client.NOT_FOUND, res.status_int)
|
||||||
|
|
||||||
@ddt.data((True, True, 'detail_list'), (True, False, 'summary_list'),
|
@ddt.data((True, True, 'detail_list'), (True, False, 'summary_list'),
|
||||||
@ -150,12 +157,12 @@ class SnapshotManageTest(test.TestCase):
|
|||||||
if clustered:
|
if clustered:
|
||||||
host = None
|
host = None
|
||||||
cluster_name = 'mycluster'
|
cluster_name = 'mycluster'
|
||||||
version = '3.17'
|
version = mv.MANAGE_EXISTING_CLUSTER
|
||||||
kwargs = {'cluster': cluster_name}
|
kwargs = {'cluster': cluster_name}
|
||||||
else:
|
else:
|
||||||
host = 'fakehost'
|
host = 'fakehost'
|
||||||
cluster_name = None
|
cluster_name = None
|
||||||
version = '3.8'
|
version = mv.MANAGE_EXISTING_LIST
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
service = objects.Service(disabled=False, host='fakehost',
|
service = objects.Service(disabled=False, host='fakehost',
|
||||||
cluster_name=cluster_name)
|
cluster_name=cluster_name)
|
||||||
@ -183,12 +190,13 @@ class SnapshotManageTest(test.TestCase):
|
|||||||
mock.ANY, None, host=host, binary='cinder-volume',
|
mock.ANY, None, host=host, binary='cinder-volume',
|
||||||
cluster_name=cluster_name)
|
cluster_name=cluster_name)
|
||||||
|
|
||||||
@ddt.data('3.8', '3.17')
|
@ddt.data(mv.MANAGE_EXISTING_LIST, mv.MANAGE_EXISTING_CLUSTER)
|
||||||
def test_get_manageable_missing_host(self, version):
|
def test_get_manageable_missing_host(self, version):
|
||||||
res = self._get_resp_get(None, True, False, version=version)
|
res = self._get_resp_get(None, True, False, version=version)
|
||||||
self.assertEqual(http_client.BAD_REQUEST, res.status_int)
|
self.assertEqual(http_client.BAD_REQUEST, res.status_int)
|
||||||
|
|
||||||
def test_get_manageable_both_host_cluster(self):
|
def test_get_manageable_both_host_cluster(self):
|
||||||
res = self._get_resp_get('host', True, False, version='3.17',
|
res = self._get_resp_get('host', True, False,
|
||||||
|
version=mv.MANAGE_EXISTING_CLUSTER,
|
||||||
cluster='cluster')
|
cluster='cluster')
|
||||||
self.assertEqual(http_client.BAD_REQUEST, res.status_int)
|
self.assertEqual(http_client.BAD_REQUEST, res.status_int)
|
||||||
|
@ -17,7 +17,7 @@ import ddt
|
|||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import snapshots
|
from cinder.api.v3 import snapshots
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
@ -54,9 +54,8 @@ def create_snapshot_query_with_metadata(metadata_query_string,
|
|||||||
"""Helper to create metadata querystring with microversion"""
|
"""Helper to create metadata querystring with microversion"""
|
||||||
req = fakes.HTTPRequest.blank('/v3/snapshots?metadata=' +
|
req = fakes.HTTPRequest.blank('/v3/snapshots?metadata=' +
|
||||||
metadata_query_string)
|
metadata_query_string)
|
||||||
req.headers["OpenStack-API-Version"] = "volume " + api_microversion
|
req.headers = mv.get_mv_header(api_microversion)
|
||||||
req.api_version_request = api_version.APIVersionRequest(
|
req.api_version_request = mv.get_api_version(api_microversion)
|
||||||
api_microversion)
|
|
||||||
|
|
||||||
return req
|
return req
|
||||||
|
|
||||||
@ -69,7 +68,9 @@ class SnapshotApiTest(test.TestCase):
|
|||||||
self.controller = snapshots.SnapshotsController()
|
self.controller = snapshots.SnapshotsController()
|
||||||
self.ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, True)
|
self.ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, True)
|
||||||
|
|
||||||
@ddt.data('3.14', '3.13', '3.41')
|
@ddt.data(mv.GROUP_SNAPSHOTS,
|
||||||
|
mv.get_prior_version(mv.GROUP_SNAPSHOTS),
|
||||||
|
mv.SNAPSHOT_LIST_USER_ID)
|
||||||
@mock.patch('cinder.db.snapshot_metadata_get', return_value=dict())
|
@mock.patch('cinder.db.snapshot_metadata_get', return_value=dict())
|
||||||
@mock.patch('cinder.objects.Volume.get_by_id')
|
@mock.patch('cinder.objects.Volume.get_by_id')
|
||||||
@mock.patch('cinder.objects.Snapshot.get_by_id')
|
@mock.patch('cinder.objects.Snapshot.get_by_id')
|
||||||
@ -91,20 +92,20 @@ class SnapshotApiTest(test.TestCase):
|
|||||||
snapshot_get_by_id.return_value = snapshot_obj
|
snapshot_get_by_id.return_value = snapshot_obj
|
||||||
volume_get_by_id.return_value = fake_volume_obj
|
volume_get_by_id.return_value = fake_volume_obj
|
||||||
req = fakes.HTTPRequest.blank('/v3/snapshots/%s' % UUID)
|
req = fakes.HTTPRequest.blank('/v3/snapshots/%s' % UUID)
|
||||||
req.api_version_request = api_version.APIVersionRequest(max_ver)
|
req.api_version_request = mv.get_api_version(max_ver)
|
||||||
resp_dict = self.controller.show(req, UUID)
|
resp_dict = self.controller.show(req, UUID)
|
||||||
|
|
||||||
self.assertIn('snapshot', resp_dict)
|
self.assertIn('snapshot', resp_dict)
|
||||||
self.assertEqual(UUID, resp_dict['snapshot']['id'])
|
self.assertEqual(UUID, resp_dict['snapshot']['id'])
|
||||||
self.assertIn('updated_at', resp_dict['snapshot'])
|
self.assertIn('updated_at', resp_dict['snapshot'])
|
||||||
if max_ver == '3.14':
|
if max_ver == mv.SNAPSHOT_LIST_USER_ID:
|
||||||
|
self.assertIn('user_id', resp_dict['snapshot'])
|
||||||
|
elif max_ver == mv.GROUP_SNAPSHOTS:
|
||||||
self.assertIn('group_snapshot_id', resp_dict['snapshot'])
|
self.assertIn('group_snapshot_id', resp_dict['snapshot'])
|
||||||
self.assertNotIn('user_id', resp_dict['snapshot'])
|
self.assertNotIn('user_id', resp_dict['snapshot'])
|
||||||
elif max_ver == '3.13':
|
else:
|
||||||
self.assertNotIn('group_snapshot_id', resp_dict['snapshot'])
|
self.assertNotIn('group_snapshot_id', resp_dict['snapshot'])
|
||||||
self.assertNotIn('user_id', resp_dict['snapshot'])
|
self.assertNotIn('user_id', resp_dict['snapshot'])
|
||||||
elif max_ver == '3.41':
|
|
||||||
self.assertIn('user_id', resp_dict['snapshot'])
|
|
||||||
|
|
||||||
def test_snapshot_show_invalid_id(self):
|
def test_snapshot_show_invalid_id(self):
|
||||||
snapshot_id = INVALID_UUID
|
snapshot_id = INVALID_UUID
|
||||||
@ -144,7 +145,7 @@ class SnapshotApiTest(test.TestCase):
|
|||||||
# Generic filtering is introduced since '3,31' and we add
|
# Generic filtering is introduced since '3,31' and we add
|
||||||
# 'availability_zone' support by using generic filtering.
|
# 'availability_zone' support by using generic filtering.
|
||||||
req = fakes.HTTPRequest.blank(url, use_admin_context=is_admin_user,
|
req = fakes.HTTPRequest.blank(url, use_admin_context=is_admin_user,
|
||||||
version='3.31')
|
version=mv.RESOURCE_FILTER)
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
|
|
||||||
self.assertEqual(1, len(res_dict['snapshots']))
|
self.assertEqual(1, len(res_dict['snapshots']))
|
||||||
@ -154,12 +155,13 @@ class SnapshotApiTest(test.TestCase):
|
|||||||
self._create_snapshot(name='test1')
|
self._create_snapshot(name='test1')
|
||||||
self._create_snapshot(name='test2')
|
self._create_snapshot(name='test2')
|
||||||
|
|
||||||
req = fakes.HTTPRequest.blank('/v3/snapshots?sort_key=name',
|
req = fakes.HTTPRequest.blank(
|
||||||
version='3.29')
|
'/v3/snapshots?sort_key=name',
|
||||||
|
version=mv.get_prior_version(mv.SNAPSHOT_SORT))
|
||||||
self.assertRaises(exception.InvalidInput, self.controller.detail, req)
|
self.assertRaises(exception.InvalidInput, self.controller.detail, req)
|
||||||
|
|
||||||
req = fakes.HTTPRequest.blank('/v3/snapshots?sort_key=name',
|
req = fakes.HTTPRequest.blank('/v3/snapshots?sort_key=name',
|
||||||
version='3.30')
|
version=mv.SNAPSHOT_SORT)
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
self.assertEqual(2, len(res_dict['snapshots']))
|
self.assertEqual(2, len(res_dict['snapshots']))
|
||||||
self.assertEqual('test2', res_dict['snapshots'][0]['name'])
|
self.assertEqual('test2', res_dict['snapshots'][0]['name'])
|
||||||
@ -171,7 +173,8 @@ class SnapshotApiTest(test.TestCase):
|
|||||||
self._create_snapshot(metadata=metadata)
|
self._create_snapshot(metadata=metadata)
|
||||||
|
|
||||||
# Create request with metadata filter key1: value1
|
# Create request with metadata filter key1: value1
|
||||||
req = create_snapshot_query_with_metadata('{"key1":"val1"}', '3.22')
|
req = create_snapshot_query_with_metadata(
|
||||||
|
'{"key1":"val1"}', mv.SNAPSHOT_LIST_METADATA_FILTER)
|
||||||
|
|
||||||
# query controller with above request
|
# query controller with above request
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
@ -184,7 +187,8 @@ class SnapshotApiTest(test.TestCase):
|
|||||||
'metadata'])
|
'metadata'])
|
||||||
|
|
||||||
# Create request with metadata filter key2: value2
|
# Create request with metadata filter key2: value2
|
||||||
req = create_snapshot_query_with_metadata('{"key2":"val2"}', '3.22')
|
req = create_snapshot_query_with_metadata(
|
||||||
|
'{"key2":"val2"}', mv.SNAPSHOT_LIST_METADATA_FILTER)
|
||||||
|
|
||||||
# query controller with above request
|
# query controller with above request
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
@ -199,7 +203,8 @@ class SnapshotApiTest(test.TestCase):
|
|||||||
|
|
||||||
# Create request with metadata filter key1: value1, key11: value11
|
# Create request with metadata filter key1: value1, key11: value11
|
||||||
req = create_snapshot_query_with_metadata(
|
req = create_snapshot_query_with_metadata(
|
||||||
'{"key1":"val1", "key11":"val11"}', '3.22')
|
'{"key1":"val1", "key11":"val11"}',
|
||||||
|
mv.SNAPSHOT_LIST_METADATA_FILTER)
|
||||||
|
|
||||||
# query controller with above request
|
# query controller with above request
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
@ -212,7 +217,8 @@ class SnapshotApiTest(test.TestCase):
|
|||||||
'snapshots'][0]['metadata'])
|
'snapshots'][0]['metadata'])
|
||||||
|
|
||||||
# Create request with metadata filter key1: value1
|
# Create request with metadata filter key1: value1
|
||||||
req = create_snapshot_query_with_metadata('{"key1":"val1"}', '3.22')
|
req = create_snapshot_query_with_metadata(
|
||||||
|
'{"key1":"val1"}', mv.SNAPSHOT_LIST_METADATA_FILTER)
|
||||||
|
|
||||||
# query controller with above request
|
# query controller with above request
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
@ -224,7 +230,19 @@ class SnapshotApiTest(test.TestCase):
|
|||||||
self.assertDictEqual({"key1": "val1", "key11": "val11"}, res_dict[
|
self.assertDictEqual({"key1": "val1", "key11": "val11"}, res_dict[
|
||||||
'snapshots'][0]['metadata'])
|
'snapshots'][0]['metadata'])
|
||||||
|
|
||||||
@ddt.data('3.30', '3.31', '3.34')
|
# Create request with metadata filter key2: value2
|
||||||
|
req = create_snapshot_query_with_metadata(
|
||||||
|
'{"key2":"val2"}', mv.SNAPSHOT_LIST_METADATA_FILTER)
|
||||||
|
|
||||||
|
# query controller with above request
|
||||||
|
res_dict = self.controller.detail(req)
|
||||||
|
|
||||||
|
# verify no snapshot is returned
|
||||||
|
self.assertEqual(0, len(res_dict['snapshots']))
|
||||||
|
|
||||||
|
@ddt.data(mv.get_prior_version(mv.RESOURCE_FILTER),
|
||||||
|
mv.RESOURCE_FILTER,
|
||||||
|
mv.LIKE_FILTER)
|
||||||
@mock.patch('cinder.api.common.reject_invalid_filters')
|
@mock.patch('cinder.api.common.reject_invalid_filters')
|
||||||
def test_snapshot_list_with_general_filter(self, version, mock_update):
|
def test_snapshot_list_with_general_filter(self, version, mock_update):
|
||||||
url = '/v3/%s/snapshots' % fake.PROJECT_ID
|
url = '/v3/%s/snapshots' % fake.PROJECT_ID
|
||||||
@ -233,8 +251,8 @@ class SnapshotApiTest(test.TestCase):
|
|||||||
use_admin_context=False)
|
use_admin_context=False)
|
||||||
self.controller.index(req)
|
self.controller.index(req)
|
||||||
|
|
||||||
if version != '3.30':
|
if version != mv.get_prior_version(mv.RESOURCE_FILTER):
|
||||||
support_like = True if version == '3.34' else False
|
support_like = True if version == mv.LIKE_FILTER else False
|
||||||
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
||||||
mock.ANY, 'snapshot',
|
mock.ANY, 'snapshot',
|
||||||
support_like)
|
support_like)
|
||||||
@ -245,7 +263,9 @@ class SnapshotApiTest(test.TestCase):
|
|||||||
self._create_snapshot(metadata=metadata)
|
self._create_snapshot(metadata=metadata)
|
||||||
|
|
||||||
# Create request with metadata filter key2: value2
|
# Create request with metadata filter key2: value2
|
||||||
req = create_snapshot_query_with_metadata('{"key2":"val2"}', '3.21')
|
req = create_snapshot_query_with_metadata(
|
||||||
|
'{"key2":"val2"}',
|
||||||
|
mv.get_prior_version(mv.SNAPSHOT_LIST_METADATA_FILTER))
|
||||||
|
|
||||||
# query controller with above request
|
# query controller with above request
|
||||||
res_dict = self.controller.detail(req)
|
res_dict = self.controller.detail(req)
|
||||||
|
@ -20,6 +20,7 @@ from six.moves import http_client
|
|||||||
from six.moves.urllib.parse import urlencode
|
from six.moves.urllib.parse import urlencode
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import router as router_v3
|
from cinder.api.v3 import router as router_v3
|
||||||
from cinder import context
|
from cinder import context
|
||||||
from cinder import objects
|
from cinder import objects
|
||||||
@ -56,13 +57,13 @@ class VolumeManageTest(test.TestCase):
|
|||||||
fake.PROJECT_ID,
|
fake.PROJECT_ID,
|
||||||
True)
|
True)
|
||||||
|
|
||||||
def _get_resp_post(self, body, version="3.8"):
|
def _get_resp_post(self, body, version=mv.MANAGE_EXISTING_LIST):
|
||||||
"""Helper to execute a POST manageable_volumes API call."""
|
"""Helper to execute a POST manageable_volumes API call."""
|
||||||
req = webob.Request.blank('/v3/%s/manageable_volumes' %
|
req = webob.Request.blank('/v3/%s/manageable_volumes' %
|
||||||
fake.PROJECT_ID)
|
fake.PROJECT_ID)
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
|
req.headers = mv.get_mv_header(version)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume ' + version
|
|
||||||
req.environ['cinder.context'] = self._admin_ctxt
|
req.environ['cinder.context'] = self._admin_ctxt
|
||||||
req.body = jsonutils.dump_as_bytes(body)
|
req.body = jsonutils.dump_as_bytes(body)
|
||||||
res = req.get_response(app())
|
res = req.get_response(app())
|
||||||
@ -88,7 +89,8 @@ class VolumeManageTest(test.TestCase):
|
|||||||
res = self._get_resp_post(body)
|
res = self._get_resp_post(body)
|
||||||
self.assertEqual(http_client.BAD_REQUEST, res.status_int, res)
|
self.assertEqual(http_client.BAD_REQUEST, res.status_int, res)
|
||||||
|
|
||||||
def _get_resp_get(self, host, detailed, paging, version="3.8", **kwargs):
|
def _get_resp_get(self, host, detailed, paging,
|
||||||
|
version=mv.MANAGE_EXISTING_LIST, **kwargs):
|
||||||
"""Helper to execute a GET os-volume-manage API call."""
|
"""Helper to execute a GET os-volume-manage API call."""
|
||||||
params = {'host': host} if host else {}
|
params = {'host': host} if host else {}
|
||||||
params.update(kwargs)
|
params.update(kwargs)
|
||||||
@ -103,8 +105,8 @@ class VolumeManageTest(test.TestCase):
|
|||||||
req = webob.Request.blank('/v3/%s/manageable_volumes%s%s' %
|
req = webob.Request.blank('/v3/%s/manageable_volumes%s%s' %
|
||||||
(fake.PROJECT_ID, detail, query_string))
|
(fake.PROJECT_ID, detail, query_string))
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
|
req.headers = mv.get_mv_header(version)
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.headers['OpenStack-API-Version'] = 'volume ' + version
|
|
||||||
req.environ['cinder.context'] = self._admin_ctxt
|
req.environ['cinder.context'] = self._admin_ctxt
|
||||||
res = req.get_response(app())
|
res = req.get_response(app())
|
||||||
return res
|
return res
|
||||||
@ -122,7 +124,9 @@ class VolumeManageTest(test.TestCase):
|
|||||||
self.assertEqual(http_client.OK, res.status_int)
|
self.assertEqual(http_client.OK, res.status_int)
|
||||||
|
|
||||||
def test_get_manageable_volumes_previous_version(self):
|
def test_get_manageable_volumes_previous_version(self):
|
||||||
res = self._get_resp_get('fakehost', False, True, version="3.7")
|
res = self._get_resp_get(
|
||||||
|
'fakehost', False, True,
|
||||||
|
version=mv.get_prior_version(mv.MANAGE_EXISTING_LIST))
|
||||||
self.assertEqual(http_client.NOT_FOUND, res.status_int)
|
self.assertEqual(http_client.NOT_FOUND, res.status_int)
|
||||||
|
|
||||||
@mock.patch('cinder.volume.api.API.get_manageable_volumes',
|
@mock.patch('cinder.volume.api.API.get_manageable_volumes',
|
||||||
@ -138,7 +142,9 @@ class VolumeManageTest(test.TestCase):
|
|||||||
self.assertEqual(http_client.OK, res.status_int)
|
self.assertEqual(http_client.OK, res.status_int)
|
||||||
|
|
||||||
def test_get_manageable_volumes_detail_previous_version(self):
|
def test_get_manageable_volumes_detail_previous_version(self):
|
||||||
res = self._get_resp_get('fakehost', True, False, version="3.7")
|
res = self._get_resp_get(
|
||||||
|
'fakehost', True, False,
|
||||||
|
version=mv.get_prior_version(mv.MANAGE_EXISTING_LIST))
|
||||||
self.assertEqual(http_client.NOT_FOUND, res.status_int)
|
self.assertEqual(http_client.NOT_FOUND, res.status_int)
|
||||||
|
|
||||||
@ddt.data((True, True, 'detail_list'), (True, False, 'summary_list'),
|
@ddt.data((True, True, 'detail_list'), (True, False, 'summary_list'),
|
||||||
@ -152,12 +158,12 @@ class VolumeManageTest(test.TestCase):
|
|||||||
if clustered:
|
if clustered:
|
||||||
host = None
|
host = None
|
||||||
cluster_name = 'mycluster'
|
cluster_name = 'mycluster'
|
||||||
version = '3.17'
|
version = mv.MANAGE_EXISTING_CLUSTER
|
||||||
kwargs = {'cluster': cluster_name}
|
kwargs = {'cluster': cluster_name}
|
||||||
else:
|
else:
|
||||||
host = 'fakehost'
|
host = 'fakehost'
|
||||||
cluster_name = None
|
cluster_name = None
|
||||||
version = '3.8'
|
version = mv.MANAGE_EXISTING_LIST
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
service = objects.Service(disabled=False, host='fakehost',
|
service = objects.Service(disabled=False, host='fakehost',
|
||||||
cluster_name=cluster_name)
|
cluster_name=cluster_name)
|
||||||
@ -185,12 +191,13 @@ class VolumeManageTest(test.TestCase):
|
|||||||
mock.ANY, None, host=host, binary='cinder-volume',
|
mock.ANY, None, host=host, binary='cinder-volume',
|
||||||
cluster_name=cluster_name)
|
cluster_name=cluster_name)
|
||||||
|
|
||||||
@ddt.data('3.8', '3.17')
|
@ddt.data(mv.MANAGE_EXISTING_LIST, mv.MANAGE_EXISTING_CLUSTER)
|
||||||
def test_get_manageable_missing_host(self, version):
|
def test_get_manageable_missing_host(self, version):
|
||||||
res = self._get_resp_get(None, True, False, version=version)
|
res = self._get_resp_get(None, True, False, version=version)
|
||||||
self.assertEqual(http_client.BAD_REQUEST, res.status_int)
|
self.assertEqual(http_client.BAD_REQUEST, res.status_int)
|
||||||
|
|
||||||
def test_get_manageable_both_host_cluster(self):
|
def test_get_manageable_both_host_cluster(self):
|
||||||
res = self._get_resp_get('host', True, False, version='3.17',
|
res = self._get_resp_get('host', True, False,
|
||||||
|
version=mv.MANAGE_EXISTING_CLUSTER,
|
||||||
cluster='cluster')
|
cluster='cluster')
|
||||||
self.assertEqual(http_client.BAD_REQUEST, res.status_int)
|
self.assertEqual(http_client.BAD_REQUEST, res.status_int)
|
||||||
|
@ -18,6 +18,7 @@ from oslo_serialization import jsonutils
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import volume_metadata
|
from cinder.api.v3 import volume_metadata
|
||||||
from cinder.api.v3 import volumes
|
from cinder.api.v3 import volumes
|
||||||
from cinder import db
|
from cinder import db
|
||||||
@ -150,7 +151,7 @@ class VolumeMetaDataTest(test.TestCase):
|
|||||||
self.volume_controller.create(req, body)
|
self.volume_controller.create(req, body)
|
||||||
|
|
||||||
def test_index(self):
|
def test_index(self):
|
||||||
req = fakes.HTTPRequest.blank(self.url, version="3.15")
|
req = fakes.HTTPRequest.blank(self.url, version=mv.ETAGS)
|
||||||
data = self.controller.index(req, self.req_id)
|
data = self.controller.index(req, self.req_id)
|
||||||
|
|
||||||
expected = {
|
expected = {
|
||||||
@ -166,14 +167,14 @@ class VolumeMetaDataTest(test.TestCase):
|
|||||||
def test_index_nonexistent_volume(self):
|
def test_index_nonexistent_volume(self):
|
||||||
self.mock_object(db, 'volume_metadata_get',
|
self.mock_object(db, 'volume_metadata_get',
|
||||||
return_volume_nonexistent)
|
return_volume_nonexistent)
|
||||||
req = fakes.HTTPRequest.blank(self.url, version="3.15")
|
req = fakes.HTTPRequest.blank(self.url, version=mv.ETAGS)
|
||||||
self.assertRaises(exception.VolumeNotFound,
|
self.assertRaises(exception.VolumeNotFound,
|
||||||
self.controller.index, req, self.url)
|
self.controller.index, req, self.url)
|
||||||
|
|
||||||
def test_index_no_data(self):
|
def test_index_no_data(self):
|
||||||
self.mock_object(db, 'volume_metadata_get',
|
self.mock_object(db, 'volume_metadata_get',
|
||||||
return_empty_volume_metadata)
|
return_empty_volume_metadata)
|
||||||
req = fakes.HTTPRequest.blank(self.url, version="3.15")
|
req = fakes.HTTPRequest.blank(self.url, version=mv.ETAGS)
|
||||||
data = self.controller.index(req, self.req_id)
|
data = self.controller.index(req, self.req_id)
|
||||||
expected = {'metadata': {}}
|
expected = {'metadata': {}}
|
||||||
result = jsonutils.loads(data.body)
|
result = jsonutils.loads(data.body)
|
||||||
@ -182,7 +183,7 @@ class VolumeMetaDataTest(test.TestCase):
|
|||||||
def test_validate_etag_true(self):
|
def test_validate_etag_true(self):
|
||||||
self.mock_object(db, 'volume_metadata_get',
|
self.mock_object(db, 'volume_metadata_get',
|
||||||
return_value={'key1': 'vanue1', 'key2': 'value2'})
|
return_value={'key1': 'vanue1', 'key2': 'value2'})
|
||||||
req = fakes.HTTPRequest.blank(self.url, version="3.15")
|
req = fakes.HTTPRequest.blank(self.url, version=mv.ETAGS)
|
||||||
req.environ['cinder.context'] = mock.Mock()
|
req.environ['cinder.context'] = mock.Mock()
|
||||||
req.if_match.etags = ['d5103bf7b26ff0310200d110da3ed186']
|
req.if_match.etags = ['d5103bf7b26ff0310200d110da3ed186']
|
||||||
self.assertTrue(self.controller._validate_etag(req, self.req_id))
|
self.assertTrue(self.controller._validate_etag(req, self.req_id))
|
||||||
@ -192,7 +193,7 @@ class VolumeMetaDataTest(test.TestCase):
|
|||||||
fake_volume = {'id': self.req_id, 'status': 'available'}
|
fake_volume = {'id': self.req_id, 'status': 'available'}
|
||||||
fake_context = mock.Mock()
|
fake_context = mock.Mock()
|
||||||
metadata_update.side_effect = return_new_volume_metadata
|
metadata_update.side_effect = return_new_volume_metadata
|
||||||
req = fakes.HTTPRequest.blank(self.url, version="3.15")
|
req = fakes.HTTPRequest.blank(self.url, version=mv.ETAGS)
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
req.content_type = "application/json"
|
req.content_type = "application/json"
|
||||||
expected = {
|
expected = {
|
||||||
@ -217,7 +218,7 @@ class VolumeMetaDataTest(test.TestCase):
|
|||||||
fake_volume = {'id': self.req_id, 'status': 'available'}
|
fake_volume = {'id': self.req_id, 'status': 'available'}
|
||||||
fake_context = mock.Mock()
|
fake_context = mock.Mock()
|
||||||
metadata_update.side_effect = return_create_volume_metadata
|
metadata_update.side_effect = return_create_volume_metadata
|
||||||
req = fakes.HTTPRequest.blank(self.url + '/key1', version="3.15")
|
req = fakes.HTTPRequest.blank(self.url + '/key1', version=mv.ETAGS)
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
body = {"meta": {"key1": "value1"}}
|
body = {"meta": {"key1": "value1"}}
|
||||||
req.body = jsonutils.dump_as_bytes(body)
|
req.body = jsonutils.dump_as_bytes(body)
|
||||||
@ -235,7 +236,7 @@ class VolumeMetaDataTest(test.TestCase):
|
|||||||
def test_create_metadata_keys_value_none(self):
|
def test_create_metadata_keys_value_none(self):
|
||||||
self.mock_object(db, 'volume_metadata_update',
|
self.mock_object(db, 'volume_metadata_update',
|
||||||
return_create_volume_metadata)
|
return_create_volume_metadata)
|
||||||
req = fakes.HTTPRequest.blank(self.url, version="3.15")
|
req = fakes.HTTPRequest.blank(self.url, version=mv.ETAGS)
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
req.headers["content-type"] = "application/json"
|
req.headers["content-type"] = "application/json"
|
||||||
body = {"meta": {"key": None}}
|
body = {"meta": {"key": None}}
|
||||||
@ -245,7 +246,7 @@ class VolumeMetaDataTest(test.TestCase):
|
|||||||
def test_update_items_value_none(self):
|
def test_update_items_value_none(self):
|
||||||
self.mock_object(db, 'volume_metadata_update',
|
self.mock_object(db, 'volume_metadata_update',
|
||||||
return_create_volume_metadata)
|
return_create_volume_metadata)
|
||||||
req = fakes.HTTPRequest.blank(self.url + '/key1', version="3.15")
|
req = fakes.HTTPRequest.blank(self.url + '/key1', version=mv.ETAGS)
|
||||||
req.method = 'PUT'
|
req.method = 'PUT'
|
||||||
body = {"metadata": {"key": None}}
|
body = {"metadata": {"key": None}}
|
||||||
req.body = jsonutils.dump_as_bytes(body)
|
req.body = jsonutils.dump_as_bytes(body)
|
||||||
|
@ -19,7 +19,7 @@ import mock
|
|||||||
import webob
|
import webob
|
||||||
|
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v2.views.volumes import ViewBuilder
|
from cinder.api.v2.views.volumes import ViewBuilder
|
||||||
from cinder.api.v3 import volumes
|
from cinder.api.v3 import volumes
|
||||||
from cinder import context
|
from cinder import context
|
||||||
@ -38,10 +38,7 @@ from cinder import utils
|
|||||||
from cinder.volume import api as volume_api
|
from cinder.volume import api as volume_api
|
||||||
from cinder.volume import api as vol_get
|
from cinder.volume import api as vol_get
|
||||||
|
|
||||||
version_header_name = 'OpenStack-API-Version'
|
|
||||||
|
|
||||||
DEFAULT_AZ = "zone1:host1"
|
DEFAULT_AZ = "zone1:host1"
|
||||||
REVERT_TO_SNAPSHOT_VERSION = '3.40'
|
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
@ -61,7 +58,7 @@ class VolumeApiTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/volumes?bootable=True')
|
req = fakes.HTTPRequest.blank('/v3/volumes?bootable=True')
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.headers = {version_header_name: 'volume 3.0'}
|
req.headers = mv.get_mv_header(mv.BASE_VERSION)
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
self.override_config('query_volume_filters', 'bootable')
|
self.override_config('query_volume_filters', 'bootable')
|
||||||
@ -77,9 +74,10 @@ class VolumeApiTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/v3/volumes?bootable=True')
|
req = fakes.HTTPRequest.blank('/v3/volumes?bootable=True')
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.headers = {version_header_name: 'volume 3.2'}
|
req.headers = mv.get_mv_header(mv.VOLUME_LIST_BOOTABLE)
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.29')
|
req.api_version_request = mv.get_api_version(
|
||||||
|
mv.VOLUME_LIST_BOOTABLE)
|
||||||
|
|
||||||
self.override_config('query_volume_filters', 'bootable')
|
self.override_config('query_volume_filters', 'bootable')
|
||||||
self.controller.index(req)
|
self.controller.index(req)
|
||||||
@ -119,8 +117,9 @@ class VolumeApiTest(test.TestCase):
|
|||||||
vols = self._create_volume_with_glance_metadata()
|
vols = self._create_volume_with_glance_metadata()
|
||||||
req = fakes.HTTPRequest.blank("/v3/volumes?glance_metadata="
|
req = fakes.HTTPRequest.blank("/v3/volumes?glance_metadata="
|
||||||
"{'image_name': 'imageTestOne'}")
|
"{'image_name': 'imageTestOne'}")
|
||||||
req.headers["OpenStack-API-Version"] = "volume 3.4"
|
req.headers = mv.get_mv_header(mv.VOLUME_LIST_GLANCE_METADATA)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.4')
|
req.api_version_request = mv.get_api_version(
|
||||||
|
mv.VOLUME_LIST_GLANCE_METADATA)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
volumes = res_dict['volumes']
|
volumes = res_dict['volumes']
|
||||||
@ -131,8 +130,8 @@ class VolumeApiTest(test.TestCase):
|
|||||||
self._create_volume_with_glance_metadata()
|
self._create_volume_with_glance_metadata()
|
||||||
req = fakes.HTTPRequest.blank("/v3/volumes?glance_metadata="
|
req = fakes.HTTPRequest.blank("/v3/volumes?glance_metadata="
|
||||||
"{'image_name': 'imageTestOne'}")
|
"{'image_name': 'imageTestOne'}")
|
||||||
req.headers["OpenStack-API-Version"] = "volume 3.0"
|
req.headers = mv.get_mv_header(mv.BASE_VERSION)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.0')
|
req.api_version_request = mv.get_api_version(mv.BASE_VERSION)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
volumes = res_dict['volumes']
|
volumes = res_dict['volumes']
|
||||||
@ -142,8 +141,8 @@ class VolumeApiTest(test.TestCase):
|
|||||||
vols = self._create_volume_with_group()
|
vols = self._create_volume_with_group()
|
||||||
req = fakes.HTTPRequest.blank(("/v3/volumes?group_id=%s") %
|
req = fakes.HTTPRequest.blank(("/v3/volumes?group_id=%s") %
|
||||||
fake.GROUP_ID)
|
fake.GROUP_ID)
|
||||||
req.headers["OpenStack-API-Version"] = "volume 3.10"
|
req.headers = mv.get_mv_header(mv.VOLUME_LIST_GROUP)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.10')
|
req.api_version_request = mv.get_api_version(mv.VOLUME_LIST_GROUP)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
volumes = res_dict['volumes']
|
volumes = res_dict['volumes']
|
||||||
@ -154,26 +153,29 @@ class VolumeApiTest(test.TestCase):
|
|||||||
self._create_volume_with_group()
|
self._create_volume_with_group()
|
||||||
req = fakes.HTTPRequest.blank(("/v3/volumes?group_id=%s") %
|
req = fakes.HTTPRequest.blank(("/v3/volumes?group_id=%s") %
|
||||||
fake.GROUP_ID)
|
fake.GROUP_ID)
|
||||||
req.headers["OpenStack-API-Version"] = "volume 3.9"
|
req.headers = mv.get_mv_header(mv.BACKUP_UPDATE)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.9')
|
req.api_version_request = mv.get_api_version(mv.BACKUP_UPDATE)
|
||||||
req.environ['cinder.context'] = self.ctxt
|
req.environ['cinder.context'] = self.ctxt
|
||||||
res_dict = self.controller.index(req)
|
res_dict = self.controller.index(req)
|
||||||
volumes = res_dict['volumes']
|
volumes = res_dict['volumes']
|
||||||
self.assertEqual(2, len(volumes))
|
self.assertEqual(2, len(volumes))
|
||||||
|
|
||||||
def _fake_volumes_summary_request(self, version='3.12', all_tenant=False,
|
def _fake_volumes_summary_request(self,
|
||||||
|
version=mv.VOLUME_SUMMARY,
|
||||||
|
all_tenant=False,
|
||||||
is_admin=False):
|
is_admin=False):
|
||||||
req_url = '/v3/volumes/summary'
|
req_url = '/v3/volumes/summary'
|
||||||
if all_tenant:
|
if all_tenant:
|
||||||
req_url += '?all_tenants=True'
|
req_url += '?all_tenants=True'
|
||||||
req = fakes.HTTPRequest.blank(req_url, use_admin_context=is_admin)
|
req = fakes.HTTPRequest.blank(req_url, use_admin_context=is_admin)
|
||||||
req.headers = {'OpenStack-API-Version': 'volume ' + version}
|
req.headers = mv.get_mv_header(version)
|
||||||
req.api_version_request = api_version.APIVersionRequest(version)
|
req.api_version_request = mv.get_api_version(version)
|
||||||
return req
|
return req
|
||||||
|
|
||||||
def test_volumes_summary_in_unsupport_version(self):
|
def test_volumes_summary_in_unsupport_version(self):
|
||||||
"""Function call to test summary volumes API in unsupported version"""
|
"""Function call to test summary volumes API in unsupported version"""
|
||||||
req = self._fake_volumes_summary_request(version='3.7')
|
req = self._fake_volumes_summary_request(
|
||||||
|
version=mv.get_prior_version(mv.VOLUME_SUMMARY))
|
||||||
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
self.assertRaises(exception.VersionNotFoundForAPIMethod,
|
||||||
self.controller.summary, req)
|
self.controller.summary, req)
|
||||||
|
|
||||||
@ -196,11 +198,12 @@ class VolumeApiTest(test.TestCase):
|
|||||||
self.assertEqual(expected, res_dict)
|
self.assertEqual(expected, res_dict)
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
('3.35', {'volume-summary': {'total_size': 0.0,
|
(mv.get_prior_version(mv.VOLUME_SUMMARY_METADATA),
|
||||||
'total_count': 0}}),
|
{'volume-summary': {'total_size': 0.0,
|
||||||
('3.36', {'volume-summary': {'total_size': 0.0,
|
'total_count': 0}}),
|
||||||
'total_count': 0,
|
(mv.VOLUME_SUMMARY_METADATA, {'volume-summary': {'total_size': 0.0,
|
||||||
'metadata': {}}}))
|
'total_count': 0,
|
||||||
|
'metadata': {}}}))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_volume_summary_empty(self, summary_api_version, expect_result):
|
def test_volume_summary_empty(self, summary_api_version, expect_result):
|
||||||
req = self._fake_volumes_summary_request(version=summary_api_version)
|
req = self._fake_volumes_summary_request(version=summary_api_version)
|
||||||
@ -208,13 +211,15 @@ class VolumeApiTest(test.TestCase):
|
|||||||
self.assertEqual(expect_result, res_dict)
|
self.assertEqual(expect_result, res_dict)
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
('3.35', {'volume-summary': {'total_size': 2,
|
(mv.get_prior_version(mv.VOLUME_SUMMARY_METADATA),
|
||||||
'total_count': 2}}),
|
{'volume-summary': {'total_size': 2,
|
||||||
('3.36', {'volume-summary': {'total_size': 2,
|
'total_count': 2}}),
|
||||||
'total_count': 2,
|
(mv.VOLUME_SUMMARY_METADATA,
|
||||||
'metadata': {
|
{'volume-summary': {'total_size': 2,
|
||||||
'name': ['test_name1', 'test_name2'],
|
'total_count': 2,
|
||||||
'age': ['test_age']}}}))
|
'metadata': {
|
||||||
|
'name': ['test_name1', 'test_name2'],
|
||||||
|
'age': ['test_age']}}}))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_volume_summary_return_metadata(self, summary_api_version,
|
def test_volume_summary_return_metadata(self, summary_api_version,
|
||||||
expect_result):
|
expect_result):
|
||||||
@ -230,13 +235,15 @@ class VolumeApiTest(test.TestCase):
|
|||||||
self.assertEqual(expect_result, res_dict)
|
self.assertEqual(expect_result, res_dict)
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
('3.35', {'volume-summary': {'total_size': 2,
|
(mv.get_prior_version(mv.VOLUME_SUMMARY_METADATA),
|
||||||
'total_count': 2}}),
|
{'volume-summary': {'total_size': 2,
|
||||||
('3.36', {'volume-summary': {'total_size': 2,
|
'total_count': 2}}),
|
||||||
'total_count': 2,
|
(mv.VOLUME_SUMMARY_METADATA,
|
||||||
'metadata': {
|
{'volume-summary': {'total_size': 2,
|
||||||
'name': ['test_name1', 'test_name2'],
|
'total_count': 2,
|
||||||
'age': ['test_age']}}}))
|
'metadata': {
|
||||||
|
'name': ['test_name1', 'test_name2'],
|
||||||
|
'age': ['test_age']}}}))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_volume_summary_return_metadata_all_tenant(
|
def test_volume_summary_return_metadata_all_tenant(
|
||||||
self, summary_api_version, expect_result):
|
self, summary_api_version, expect_result):
|
||||||
@ -334,8 +341,9 @@ class VolumeApiTest(test.TestCase):
|
|||||||
if with_migration_status:
|
if with_migration_status:
|
||||||
volume['volume']['migration_status'] = None
|
volume['volume']['migration_status'] = None
|
||||||
|
|
||||||
# Remove group_id if max version is less than 3.13.
|
# Remove group_id if max version is less than GROUP_VOLUME.
|
||||||
if req_version and req_version.matches(None, "3.12"):
|
if req_version and req_version.matches(
|
||||||
|
None, mv.get_prior_version(mv.GROUP_VOLUME)):
|
||||||
volume['volume'].pop('group_id')
|
volume['volume'].pop('group_id')
|
||||||
|
|
||||||
return volume
|
return volume
|
||||||
@ -356,13 +364,14 @@ class VolumeApiTest(test.TestCase):
|
|||||||
'group': test_group,
|
'group': test_group,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Remove group_id if max version is less than 3.13.
|
# Remove group_id if max version is less than GROUP_VOLUME.
|
||||||
if req_version and req_version.matches(None, "3.12"):
|
if req_version and req_version.matches(
|
||||||
|
None, mv.get_prior_version(mv.GROUP_VOLUME)):
|
||||||
volume.pop('group')
|
volume.pop('group')
|
||||||
|
|
||||||
return volume
|
return volume
|
||||||
|
|
||||||
@ddt.data('3.13', '3.12')
|
@ddt.data(mv.GROUP_VOLUME, mv.get_prior_version(mv.GROUP_VOLUME))
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'cinder.api.openstack.wsgi.Controller.validate_name_and_description')
|
'cinder.api.openstack.wsgi.Controller.validate_name_and_description')
|
||||||
def test_volume_create(self, max_ver, mock_validate):
|
def test_volume_create(self, max_ver, mock_validate):
|
||||||
@ -375,14 +384,14 @@ class VolumeApiTest(test.TestCase):
|
|||||||
vol = self._vol_in_request_body()
|
vol = self._vol_in_request_body()
|
||||||
body = {"volume": vol}
|
body = {"volume": vol}
|
||||||
req = fakes.HTTPRequest.blank('/v3/volumes')
|
req = fakes.HTTPRequest.blank('/v3/volumes')
|
||||||
req.api_version_request = api_version.APIVersionRequest(max_ver)
|
req.api_version_request = mv.get_api_version(max_ver)
|
||||||
res_dict = self.controller.create(req, body)
|
res_dict = self.controller.create(req, body)
|
||||||
ex = self._expected_vol_from_controller(
|
ex = self._expected_vol_from_controller(
|
||||||
req_version=req.api_version_request)
|
req_version=req.api_version_request)
|
||||||
self.assertEqual(ex, res_dict)
|
self.assertEqual(ex, res_dict)
|
||||||
self.assertTrue(mock_validate.called)
|
self.assertTrue(mock_validate.called)
|
||||||
|
|
||||||
@ddt.data('3.14', '3.13')
|
@ddt.data(mv.GROUP_SNAPSHOTS, mv.get_prior_version(mv.GROUP_SNAPSHOTS))
|
||||||
@mock.patch.object(group_api.API, 'get')
|
@mock.patch.object(group_api.API, 'get')
|
||||||
@mock.patch.object(db.sqlalchemy.api, '_volume_type_get_full',
|
@mock.patch.object(db.sqlalchemy.api, '_volume_type_get_full',
|
||||||
autospec=True)
|
autospec=True)
|
||||||
@ -405,7 +414,7 @@ class VolumeApiTest(test.TestCase):
|
|||||||
group_id=fake.GROUP_ID)
|
group_id=fake.GROUP_ID)
|
||||||
body = {"volume": vol}
|
body = {"volume": vol}
|
||||||
req = fakes.HTTPRequest.blank('/v3/volumes')
|
req = fakes.HTTPRequest.blank('/v3/volumes')
|
||||||
req.api_version_request = api_version.APIVersionRequest(max_ver)
|
req.api_version_request = mv.get_api_version(max_ver)
|
||||||
res_dict = self.controller.create(req, body)
|
res_dict = self.controller.create(req, body)
|
||||||
ex = self._expected_vol_from_controller(
|
ex = self._expected_vol_from_controller(
|
||||||
snapshot_id=snapshot_id,
|
snapshot_id=snapshot_id,
|
||||||
@ -450,23 +459,26 @@ class VolumeApiTest(test.TestCase):
|
|||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
||||||
req, body)
|
req, body)
|
||||||
|
|
||||||
@ddt.data('3.30', '3.31', '3.34')
|
@ddt.data(mv.get_prior_version(mv.RESOURCE_FILTER), mv.RESOURCE_FILTER,
|
||||||
|
mv.LIKE_FILTER)
|
||||||
@mock.patch.object(volume_api.API, 'check_volume_filters', mock.Mock())
|
@mock.patch.object(volume_api.API, 'check_volume_filters', mock.Mock())
|
||||||
@mock.patch.object(utils, 'add_visible_admin_metadata', mock.Mock())
|
@mock.patch.object(utils, 'add_visible_admin_metadata', mock.Mock())
|
||||||
@mock.patch('cinder.api.common.reject_invalid_filters')
|
@mock.patch('cinder.api.common.reject_invalid_filters')
|
||||||
def test_list_volume_with_general_filter(self, version, mock_update):
|
def test_list_volume_with_general_filter(self, version, mock_update):
|
||||||
req = fakes.HTTPRequest.blank('/v3/volumes', version=version)
|
req = fakes.HTTPRequest.blank('/v3/volumes', version=version)
|
||||||
self.controller.index(req)
|
self.controller.index(req)
|
||||||
if version != '3.30':
|
if version >= mv.RESOURCE_FILTER:
|
||||||
support_like = True if version == '3.34' else False
|
support_like = True if version == mv.LIKE_FILTER else False
|
||||||
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
mock_update.assert_called_once_with(req.environ['cinder.context'],
|
||||||
mock.ANY, 'volume',
|
mock.ANY, 'volume',
|
||||||
support_like)
|
support_like)
|
||||||
|
|
||||||
@ddt.data({'admin': True, 'version': '3.21'},
|
@ddt.data({'admin': True, 'version': mv.VOLUME_DETAIL_PROVIDER_ID},
|
||||||
{'admin': False, 'version': '3.21'},
|
{'admin': False, 'version': mv.VOLUME_DETAIL_PROVIDER_ID},
|
||||||
{'admin': True, 'version': '3.20'},
|
{'admin': True,
|
||||||
{'admin': False, 'version': '3.20'})
|
'version': mv.get_prior_version(mv.VOLUME_DETAIL_PROVIDER_ID)},
|
||||||
|
{'admin': False,
|
||||||
|
'version': mv.get_prior_version(mv.VOLUME_DETAIL_PROVIDER_ID)})
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_volume_show_provider_id(self, admin, version):
|
def test_volume_show_provider_id(self, admin, version):
|
||||||
self.mock_object(volume_api.API, 'get', v2_fakes.fake_volume_api_get)
|
self.mock_object(volume_api.API, 'get', v2_fakes.fake_volume_api_get)
|
||||||
@ -482,8 +494,8 @@ class VolumeApiTest(test.TestCase):
|
|||||||
res_dict = self.controller.show(req, fake.VOLUME_ID)
|
res_dict = self.controller.show(req, fake.VOLUME_ID)
|
||||||
req_version = req.api_version_request
|
req_version = req.api_version_request
|
||||||
# provider_id is in view if min version is greater than or equal to
|
# provider_id is in view if min version is greater than or equal to
|
||||||
# 3.21 for admin.
|
# VOLUME_DETAIL_PROVIDER_ID for admin.
|
||||||
if req_version.matches("3.21", None) and admin:
|
if req_version.matches(mv.VOLUME_DETAIL_PROVIDER_ID, None) and admin:
|
||||||
self.assertIn('provider_id', res_dict['volume'])
|
self.assertIn('provider_id', res_dict['volume'])
|
||||||
else:
|
else:
|
||||||
self.assertNotIn('provider_id', res_dict['volume'])
|
self.assertNotIn('provider_id', res_dict['volume'])
|
||||||
@ -516,10 +528,9 @@ class VolumeApiTest(test.TestCase):
|
|||||||
mock_latest.side_effect = exception.VolumeSnapshotNotFound(volume_id=
|
mock_latest.side_effect = exception.VolumeSnapshotNotFound(volume_id=
|
||||||
'fake_id')
|
'fake_id')
|
||||||
req = fakes.HTTPRequest.blank('/v3/volumes/fake_id/revert')
|
req = fakes.HTTPRequest.blank('/v3/volumes/fake_id/revert')
|
||||||
req.headers = {'OpenStack-API-Version':
|
req.headers = mv.get_mv_header(mv.VOLUME_REVERT)
|
||||||
'volume %s' % REVERT_TO_SNAPSHOT_VERSION}
|
req.api_version_request = mv.get_api_version(
|
||||||
req.api_version_request = api_version.APIVersionRequest(
|
mv.VOLUME_REVERT)
|
||||||
REVERT_TO_SNAPSHOT_VERSION)
|
|
||||||
|
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.revert,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.revert,
|
||||||
req, 'fake_id', {'revert': {'snapshot_id':
|
req, 'fake_id', {'revert': {'snapshot_id':
|
||||||
@ -534,10 +545,9 @@ class VolumeApiTest(test.TestCase):
|
|||||||
fake_snapshot = self._fake_create_snapshot(fake.UUID1)
|
fake_snapshot = self._fake_create_snapshot(fake.UUID1)
|
||||||
mock_latest.return_value = fake_snapshot
|
mock_latest.return_value = fake_snapshot
|
||||||
req = fakes.HTTPRequest.blank('/v3/volumes/fake_id/revert')
|
req = fakes.HTTPRequest.blank('/v3/volumes/fake_id/revert')
|
||||||
req.headers = {'OpenStack-API-Version':
|
req.headers = mv.get_mv_header(mv.VOLUME_REVERT)
|
||||||
'volume %s' % REVERT_TO_SNAPSHOT_VERSION}
|
req.api_version_request = mv.get_api_version(
|
||||||
req.api_version_request = api_version.APIVersionRequest(
|
mv.VOLUME_REVERT)
|
||||||
REVERT_TO_SNAPSHOT_VERSION)
|
|
||||||
|
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.revert,
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.revert,
|
||||||
req, 'fake_id', {'revert': {'snapshot_id':
|
req, 'fake_id', {'revert': {'snapshot_id':
|
||||||
@ -557,10 +567,9 @@ class VolumeApiTest(test.TestCase):
|
|||||||
mock_latest.return_value = fake_snapshot
|
mock_latest.return_value = fake_snapshot
|
||||||
req = fakes.HTTPRequest.blank('/v3/volumes/%s/revert'
|
req = fakes.HTTPRequest.blank('/v3/volumes/%s/revert'
|
||||||
% fake_volume['id'])
|
% fake_volume['id'])
|
||||||
req.headers = {'OpenStack-API-Version':
|
req.headers = mv.get_mv_header(mv.VOLUME_REVERT)
|
||||||
'volume %s' % REVERT_TO_SNAPSHOT_VERSION}
|
req.api_version_request = mv.get_api_version(
|
||||||
req.api_version_request = api_version.APIVersionRequest(
|
mv.VOLUME_REVERT)
|
||||||
REVERT_TO_SNAPSHOT_VERSION)
|
|
||||||
# update volume's status failed
|
# update volume's status failed
|
||||||
mock_update.side_effect = [False, True]
|
mock_update.side_effect = [False, True]
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ from oslo_serialization import jsonutils
|
|||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.v3 import router as router_v3
|
from cinder.api.v3 import router as router_v3
|
||||||
from cinder.api.v3 import workers
|
from cinder.api.v3 import workers
|
||||||
from cinder import context
|
from cinder import context
|
||||||
@ -61,7 +62,7 @@ class WorkersTestCase(test.TestCase):
|
|||||||
overwrite=False)
|
overwrite=False)
|
||||||
self.controller = workers.create_resource()
|
self.controller = workers.create_resource()
|
||||||
|
|
||||||
def _get_resp_post(self, body, version='3.24', ctxt=None):
|
def _get_resp_post(self, body, version=mv.WORKERS_CLEANUP, ctxt=None):
|
||||||
"""Helper to execute a POST workers API call."""
|
"""Helper to execute a POST workers API call."""
|
||||||
req = webob.Request.blank('/v3/%s/workers/cleanup' % fake.PROJECT_ID)
|
req = webob.Request.blank('/v3/%s/workers/cleanup' % fake.PROJECT_ID)
|
||||||
req.method = 'POST'
|
req.method = 'POST'
|
||||||
@ -74,7 +75,7 @@ class WorkersTestCase(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch('cinder.scheduler.rpcapi.SchedulerAPI.work_cleanup')
|
@mock.patch('cinder.scheduler.rpcapi.SchedulerAPI.work_cleanup')
|
||||||
def test_cleanup_old_api_version(self, rpc_mock):
|
def test_cleanup_old_api_version(self, rpc_mock):
|
||||||
res = self._get_resp_post({}, '3.19')
|
res = self._get_resp_post({}, mv.get_prior_version(mv.WORKERS_CLEANUP))
|
||||||
self.assertEqual(http_client.NOT_FOUND, res.status_code)
|
self.assertEqual(http_client.NOT_FOUND, res.status_code)
|
||||||
rpc_mock.assert_not_called()
|
rpc_mock.assert_not_called()
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ from oslo_config import cfg
|
|||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
|
|
||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import api_version_request as api_version
|
from cinder.api.openstack import api_version_request as api_version
|
||||||
from cinder.api.v3 import messages
|
from cinder.api.v3 import messages
|
||||||
from cinder import context
|
from cinder import context
|
||||||
@ -128,8 +129,8 @@ class MessageApiTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank(url)
|
req = fakes.HTTPRequest.blank(url)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.headers = {version_header_name: 'volume 3.5'}
|
req.headers = mv.get_mv_header(mv.MESSAGES_PAGINATION)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.30')
|
req.api_version_request = mv.get_api_version(mv.RESOURCE_FILTER)
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
@ -139,8 +140,8 @@ class MessageApiTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank(url)
|
req = fakes.HTTPRequest.blank(url)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.headers = {version_header_name: 'volume 3.5'}
|
req.headers = mv.get_mv_header(mv.MESSAGES_PAGINATION)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.30')
|
req.api_version_request = mv.get_api_version(mv.RESOURCE_FILTER)
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
@ -149,12 +150,14 @@ class MessageApiTest(test.TestCase):
|
|||||||
def test_get_all_messages_with_limit_wrong_version(self):
|
def test_get_all_messages_with_limit_wrong_version(self):
|
||||||
self.create_message_for_tests()
|
self.create_message_for_tests()
|
||||||
|
|
||||||
|
PRE_MESSAGES_PAGINATION = mv.get_prior_version(mv.MESSAGES_PAGINATION)
|
||||||
|
|
||||||
url = '/v3/messages?limit=1'
|
url = '/v3/messages?limit=1'
|
||||||
req = fakes.HTTPRequest.blank(url)
|
req = fakes.HTTPRequest.blank(url)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.headers["OpenStack-API-Version"] = "volume 3.3"
|
req.headers = mv.get_mv_header(PRE_MESSAGES_PAGINATION)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.3')
|
req.api_version_request = mv.get_api_version(PRE_MESSAGES_PAGINATION)
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
@ -167,8 +170,8 @@ class MessageApiTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank(url)
|
req = fakes.HTTPRequest.blank(url)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.headers["OpenStack-API-Version"] = "volume 3.5"
|
req.headers = mv.get_mv_header(mv.MESSAGES_PAGINATION)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.5')
|
req.api_version_request = mv.get_api_version(mv.MESSAGES_PAGINATION)
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
@ -181,8 +184,8 @@ class MessageApiTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank(url)
|
req = fakes.HTTPRequest.blank(url)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.headers["OpenStack-API-Version"] = "volume 3.5"
|
req.headers = mv.get_mv_header(mv.MESSAGES_PAGINATION)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.5')
|
req.api_version_request = mv.get_api_version(mv.MESSAGES_PAGINATION)
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
@ -196,8 +199,8 @@ class MessageApiTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank(url)
|
req = fakes.HTTPRequest.blank(url)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.headers["OpenStack-API-Version"] = "volume 3.5"
|
req.headers = mv.get_mv_header(mv.MESSAGES_PAGINATION)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.5')
|
req.api_version_request = mv.get_api_version(mv.MESSAGES_PAGINATION)
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
@ -210,8 +213,8 @@ class MessageApiTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank(url)
|
req = fakes.HTTPRequest.blank(url)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.headers["OpenStack-API-Version"] = "volume 3.5"
|
req.headers = mv.get_mv_header(mv.MESSAGES_PAGINATION)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.5')
|
req.api_version_request = mv.get_api_version(mv.MESSAGES_PAGINATION)
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
@ -242,8 +245,8 @@ class MessageApiTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank(url)
|
req = fakes.HTTPRequest.blank(url)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.headers = {version_header_name: 'volume 3.5'}
|
req.headers = mv.get_mv_header(mv.MESSAGES_PAGINATION)
|
||||||
req.api_version_request = api_version.APIVersionRequest('3.30')
|
req.api_version_request = mv.get_api_version(mv.RESOURCE_FILTER)
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
res = self.controller.index(req)
|
res = self.controller.index(req)
|
||||||
@ -263,7 +266,7 @@ class MessageApiTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank(url)
|
req = fakes.HTTPRequest.blank(url)
|
||||||
req.method = 'GET'
|
req.method = 'GET'
|
||||||
req.content_type = 'application/json'
|
req.content_type = 'application/json'
|
||||||
req.headers = {version_header_name: 'volume 3.5'}
|
req.headers = mv.get_mv_header(mv.MESSAGES_PAGINATION)
|
||||||
req.api_version_request = api_version.max_api_version()
|
req.api_version_request = api_version.max_api_version()
|
||||||
req.environ['cinder.context'].is_admin = True
|
req.environ['cinder.context'].is_admin = True
|
||||||
|
|
||||||
|
@ -1910,20 +1910,20 @@ class API(base.Base):
|
|||||||
def _check_boolean_filter_value(self, key, val, strict=False):
|
def _check_boolean_filter_value(self, key, val, strict=False):
|
||||||
"""Boolean filter values in Volume GET.
|
"""Boolean filter values in Volume GET.
|
||||||
|
|
||||||
Before V3.2, all values other than 'False', 'false', 'FALSE' were
|
Before VOLUME_LIST_BOOTABLE, all values other than 'False', 'false',
|
||||||
trated as True for specific boolean filter parameters in Volume
|
'FALSE' were trated as True for specific boolean filter parameters in
|
||||||
GET request.
|
Volume GET request.
|
||||||
|
|
||||||
But V3.2 onwards, only true/True/0/1/False/false parameters are
|
But VOLUME_LIST_BOOTABLE onwards, only true/True/0/1/False/false
|
||||||
supported.
|
parameters are supported.
|
||||||
All other input values to specific boolean filter parameter will
|
All other input values to specific boolean filter parameter will
|
||||||
lead to raising exception.
|
lead to raising exception.
|
||||||
|
|
||||||
This changes API behavior. So, micro version introduced for V3.2
|
This changes API behavior. So, micro version introduced for
|
||||||
onwards.
|
VOLUME_LIST_BOOTABLE onwards.
|
||||||
"""
|
"""
|
||||||
if strict:
|
if strict:
|
||||||
# for updated behavior, from V3.2 onwards.
|
# for updated behavior, from VOLUME_LIST_BOOTABLE onwards.
|
||||||
# To translate any true/false/t/f/0/1 to True/False
|
# To translate any true/false/t/f/0/1 to True/False
|
||||||
# which is only acceptable format in database queries.
|
# which is only acceptable format in database queries.
|
||||||
try:
|
try:
|
||||||
@ -1933,7 +1933,7 @@ class API(base.Base):
|
|||||||
'value': val}
|
'value': val}
|
||||||
raise exception.InvalidInput(reason=msg)
|
raise exception.InvalidInput(reason=msg)
|
||||||
else:
|
else:
|
||||||
# For existing behavior(before version 3.2)
|
# For existing behavior(before version VOLUME_LIST_BOOTABLE)
|
||||||
accepted_true = ['True', 'true', 'TRUE']
|
accepted_true = ['True', 'true', 'TRUE']
|
||||||
accepted_false = ['False', 'false', 'FALSE']
|
accepted_false = ['False', 'false', 'FALSE']
|
||||||
|
|
||||||
|
@ -278,8 +278,17 @@ necessary to add changes to other places which describe your change:
|
|||||||
be enough information that it could be used by the docs team for
|
be enough information that it could be used by the docs team for
|
||||||
release notes.
|
release notes.
|
||||||
|
|
||||||
|
* Constants should be used in the code to minimize errors on microversion
|
||||||
|
merge conflicts. Define a constant for the new microversion in the
|
||||||
|
``cinder/api/microversions.py`` file and use that in the rest of the code.
|
||||||
|
|
||||||
* Update the expected versions in affected tests.
|
* Update the expected versions in affected tests.
|
||||||
|
|
||||||
|
* API changes should almost always include a release note announcing the
|
||||||
|
availability of the new API functionality. The description of the API change
|
||||||
|
should indicate which microversion is required for the change, and it should
|
||||||
|
refer to the numerical value of the microversion and not its constant name.
|
||||||
|
|
||||||
Allocating a microversion
|
Allocating a microversion
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user