185 lines
8.1 KiB
Python
185 lines
8.1 KiB
Python
# Copyright 2015 NEC Corporation. All rights reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import testtools
|
|
|
|
from tempest.lib.common import api_version_request
|
|
from tempest.lib import exceptions
|
|
|
|
|
|
LATEST_MICROVERSION = 'latest'
|
|
|
|
|
|
class BaseMicroversionTest(object):
|
|
"""Mixin class for API microversion test class."""
|
|
|
|
# NOTE: Basically, each microversion is small API change and we
|
|
# can use the same tests for most microversions in most cases.
|
|
# So it is nice to define the test class as possible to run
|
|
# for all microversions. We need to define microversion range
|
|
# (min_microversion, max_microversion) on each test class if necessary.
|
|
min_microversion = None
|
|
max_microversion = LATEST_MICROVERSION
|
|
volume_min_microversion = None
|
|
volume_max_microversion = LATEST_MICROVERSION
|
|
placement_min_microversion = None
|
|
placement_max_microversion = LATEST_MICROVERSION
|
|
|
|
|
|
def check_skip_with_microversion(test_min_version, test_max_version,
|
|
cfg_min_version, cfg_max_version):
|
|
"""Checks API microversions range and returns whether test needs to be skip
|
|
|
|
Compare the test and configured microversion range and returns
|
|
whether test microversion range is out of configured one.
|
|
This method can be used to skip the test based on configured and test
|
|
microversion range.
|
|
|
|
:param test_min_version: Test Minimum Microversion
|
|
:param test_max_version: Test Maximum Microversion
|
|
:param cfg_min_version: Configured Minimum Microversion
|
|
:param cfg_max_version: Configured Maximum Microversion
|
|
:returns: boolean
|
|
"""
|
|
|
|
min_version = api_version_request.APIVersionRequest(test_min_version)
|
|
max_version = api_version_request.APIVersionRequest(test_max_version)
|
|
config_min_version = api_version_request.APIVersionRequest(cfg_min_version)
|
|
config_max_version = api_version_request.APIVersionRequest(cfg_max_version)
|
|
if ((min_version > max_version) or
|
|
(config_min_version > config_max_version)):
|
|
msg = ("Test Class versions [%s - %s]. "
|
|
"Configuration versions [%s - %s]."
|
|
% (min_version.get_string(),
|
|
max_version.get_string(),
|
|
config_min_version.get_string(),
|
|
config_max_version.get_string()))
|
|
raise exceptions.InvalidAPIVersionRange(msg)
|
|
|
|
# NOTE: Select tests which are in range of configuration like
|
|
# config min config max
|
|
# ----------------+--------------------------+----------------
|
|
# ...don't-select|
|
|
# ...select... ...select... ...select...
|
|
# |don't-select...
|
|
# ......................select............................
|
|
if (max_version < config_min_version or
|
|
config_max_version < min_version):
|
|
msg = ("The microversion range[%s - %s] of this test is out of the "
|
|
"configuration range[%s - %s]."
|
|
% (min_version.get_string(),
|
|
max_version.get_string(),
|
|
config_min_version.get_string(),
|
|
config_max_version.get_string()))
|
|
raise testtools.TestCase.skipException(msg)
|
|
|
|
|
|
def select_request_microversion(test_min_version, cfg_min_version):
|
|
"""Select microversion from test and configuration min version.
|
|
|
|
Compare requested microversion and return the maximum
|
|
microversion out of those.
|
|
|
|
:param test_min_version: Test Minimum Microversion
|
|
:param cfg_min_version: Configured Minimum Microversion
|
|
:returns: Selected microversion string
|
|
"""
|
|
|
|
test_version = api_version_request.APIVersionRequest(test_min_version)
|
|
cfg_version = api_version_request.APIVersionRequest(cfg_min_version)
|
|
max_version = cfg_version if cfg_version >= test_version else test_version
|
|
return max_version.get_string()
|
|
|
|
|
|
def assert_version_header_matches_request(api_microversion_header_name,
|
|
api_microversion,
|
|
response_header):
|
|
"""Checks API microversion in response header
|
|
|
|
Verify whether microversion is present in response header
|
|
and with specified 'api_microversion' value.
|
|
|
|
:param api_microversion_header_name: Microversion header name
|
|
Example- "X-OpenStack-Nova-API-Version"
|
|
:param api_microversion: Microversion number like "2.10", type str.
|
|
:param response_header: Response header where microversion is
|
|
expected to be present.
|
|
"""
|
|
if not isinstance(api_microversion, str):
|
|
raise TypeError('api_microversion must be a string')
|
|
api_microversion_header_name = api_microversion_header_name.lower()
|
|
if (api_microversion_header_name not in response_header or
|
|
api_microversion != response_header[api_microversion_header_name]):
|
|
msg = ("Microversion header '%s' with value '%s' does not match in "
|
|
"response - %s. " % (api_microversion_header_name,
|
|
api_microversion,
|
|
response_header))
|
|
raise exceptions.InvalidHTTPResponseHeader(msg)
|
|
|
|
|
|
def compare_version_header_to_response(api_microversion_header_name,
|
|
api_microversion,
|
|
response_header,
|
|
operation='eq'):
|
|
"""Compares API microversion in response header to ``api_microversion``.
|
|
|
|
Compare the ``api_microversion`` value in response header if microversion
|
|
header is present in response, otherwise return false.
|
|
|
|
To make this function work for APIs which do not return microversion
|
|
header in response (example compute v2.0), this function does *not* raise
|
|
InvalidHTTPResponseHeader.
|
|
|
|
:param api_microversion_header_name: Microversion header name. Example:
|
|
'Openstack-Api-Version'.
|
|
:param api_microversion: Microversion number. Example:
|
|
|
|
* '2.10' for the old-style header name, 'X-OpenStack-Nova-API-Version'
|
|
* 'Compute 2.10' for the new-style header name, 'Openstack-Api-Version'
|
|
|
|
:param response_header: Response header where microversion is
|
|
expected to be present.
|
|
:param operation: The boolean operation to use to compare the
|
|
``api_microversion`` to the microversion in ``response_header``.
|
|
Can be 'lt', 'eq', 'gt', 'le', 'ne', 'ge'. Default is 'eq'. The
|
|
operation type should be based on the order of the arguments:
|
|
``api_microversion`` <operation> ``response_header`` microversion.
|
|
:returns: True if the comparison is logically true, else False if the
|
|
comparison is logically false or if ``api_microversion_header_name`` is
|
|
missing in the ``response_header``.
|
|
:raises InvalidParam: If the operation is not lt, eq, gt, le, ne or ge.
|
|
"""
|
|
api_microversion_header_name = api_microversion_header_name.lower()
|
|
if api_microversion_header_name not in response_header:
|
|
return False
|
|
|
|
op = getattr(api_version_request.APIVersionRequest,
|
|
'__%s__' % operation, None)
|
|
|
|
if op is None:
|
|
msg = ("Operation %s is invalid. Valid options include: lt, eq, gt, "
|
|
"le, ne, ge." % operation)
|
|
raise exceptions.InvalidParam(invalid_param=msg)
|
|
|
|
# Remove "volume" from "volume <microversion>", for example, so that the
|
|
# microversion can be converted to `APIVersionRequest`.
|
|
api_version = api_microversion.split(' ')[-1]
|
|
resp_version = response_header[api_microversion_header_name].split(' ')[-1]
|
|
if not op(
|
|
api_version_request.APIVersionRequest(api_version),
|
|
api_version_request.APIVersionRequest(resp_version)):
|
|
return False
|
|
|
|
return True
|