Update to microversion 2.27
This enables the use of the OpenStack-API-Version header, in addition to the older X-OpenStack-Nova-API-Version header. If the client knows that it is in a version less than 2.27, it will not send the newer header. If the client knows that is in a version >= 2.27 if it gets a response that does not have the expected response header (the newer one) it will warn. If it is in an older version, it will warn about the other one missing. A server that is 2.27 or beyond will accept both headers and respond with both. Change-Id: I1f7b1ca0fe795e4ecd333de761d96fff117969c0
This commit is contained in:
parent
2253d02266
commit
082ed80369
@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
|
||||
# when client supported the max version, and bumped sequentially, otherwise
|
||||
# the client may break due to server side new version may include some
|
||||
# backward incompatible change.
|
||||
API_MAX_VERSION = api_versions.APIVersion("2.26")
|
||||
API_MAX_VERSION = api_versions.APIVersion("2.27")
|
||||
|
@ -29,7 +29,9 @@ if not LOG.handlers:
|
||||
LOG.addHandler(logging.StreamHandler())
|
||||
|
||||
|
||||
HEADER_NAME = "X-OpenStack-Nova-API-Version"
|
||||
LEGACY_HEADER_NAME = "X-OpenStack-Nova-API-Version"
|
||||
HEADER_NAME = "OpenStack-API-Version"
|
||||
SERVICE_TYPE = "compute"
|
||||
# key is a deprecated version and value is an alternative version.
|
||||
DEPRECATED_VERSIONS = {"1.1": "2"}
|
||||
|
||||
@ -317,19 +319,25 @@ def discover_version(client, requested_version):
|
||||
|
||||
|
||||
def update_headers(headers, api_version):
|
||||
"""Set 'X-OpenStack-Nova-API-Version' header if api_version is not null"""
|
||||
"""Set microversion headers if api_version is not null"""
|
||||
|
||||
if not api_version.is_null() and api_version.ver_minor != 0:
|
||||
headers[HEADER_NAME] = api_version.get_string()
|
||||
if not api_version.is_null():
|
||||
version_string = api_version.get_string()
|
||||
if api_version.ver_minor != 0:
|
||||
headers[LEGACY_HEADER_NAME] = version_string
|
||||
if api_version.ver_minor >= 27:
|
||||
headers[HEADER_NAME] = '%s %s' % (SERVICE_TYPE, version_string)
|
||||
|
||||
|
||||
def check_headers(response, api_version):
|
||||
"""Checks that 'X-OpenStack-Nova-API-Version' header in response."""
|
||||
if api_version.ver_minor > 0 and HEADER_NAME not in response.headers:
|
||||
LOG.warning(_LW(
|
||||
"Your request was processed by a Nova API which does not support "
|
||||
"microversions (%s header is missing from response). "
|
||||
"Warning: Response may be incorrect."), HEADER_NAME)
|
||||
"""Checks that microversion header is in response."""
|
||||
if api_version.ver_minor > 0:
|
||||
if (api_version.ver_minor < 27
|
||||
and LEGACY_HEADER_NAME not in response.headers):
|
||||
_warn_missing_microversion_header(LEGACY_HEADER_NAME)
|
||||
elif (api_version.ver_minor >= 27
|
||||
and HEADER_NAME not in response.headers):
|
||||
_warn_missing_microversion_header(HEADER_NAME)
|
||||
|
||||
|
||||
def add_substitution(versioned_method):
|
||||
@ -378,3 +386,11 @@ def wraps(start_version, end_version=None):
|
||||
return substitution
|
||||
|
||||
return decor
|
||||
|
||||
|
||||
def _warn_missing_microversion_header(header_name):
|
||||
"""Log a warning about missing microversion response header."""
|
||||
LOG.warning(_LW(
|
||||
"Your request was processed by a Nova API which does not support "
|
||||
"microversions (%s header is missing from response). "
|
||||
"Warning: Response may be incorrect."), header_name)
|
||||
|
@ -144,6 +144,18 @@ class UpdateHeadersTestCase(utils.TestCase):
|
||||
{"X-OpenStack-Nova-API-Version": api_version.get_string()},
|
||||
headers)
|
||||
|
||||
def test_api_version_is_gte_27(self):
|
||||
api_version = api_versions.APIVersion("2.27")
|
||||
headers = {}
|
||||
api_versions.update_headers(headers, api_version)
|
||||
self.assertIn('X-OpenStack-Nova-API-Version', headers)
|
||||
self.assertIn('OpenStack-API-Version', headers)
|
||||
self.assertEqual(api_version.get_string(),
|
||||
headers['X-OpenStack-Nova-API-Version'])
|
||||
self.assertEqual('%s %s' % (api_versions.SERVICE_TYPE,
|
||||
api_version.get_string()),
|
||||
headers['OpenStack-API-Version'])
|
||||
|
||||
|
||||
class CheckHeadersTestCase(utils.TestCase):
|
||||
def setUp(self):
|
||||
@ -152,8 +164,9 @@ class CheckHeadersTestCase(utils.TestCase):
|
||||
self.mock_log = mock_log_patch.start()
|
||||
self.addCleanup(mock_log_patch.stop)
|
||||
|
||||
def test_microversion_is_specified(self):
|
||||
response = mock.MagicMock(headers={api_versions.HEADER_NAME: ""})
|
||||
def test_legacy_microversion_is_specified(self):
|
||||
response = mock.MagicMock(
|
||||
headers={api_versions.LEGACY_HEADER_NAME: ""})
|
||||
api_versions.check_headers(response, api_versions.APIVersion("2.2"))
|
||||
self.assertFalse(self.mock_log.warning.called)
|
||||
|
||||
@ -161,8 +174,19 @@ class CheckHeadersTestCase(utils.TestCase):
|
||||
api_versions.check_headers(response, api_versions.APIVersion("2.2"))
|
||||
self.assertTrue(self.mock_log.warning.called)
|
||||
|
||||
def test_generic_microversion_is_specified(self):
|
||||
response = mock.MagicMock(
|
||||
headers={api_versions.HEADER_NAME: ""})
|
||||
api_versions.check_headers(response, api_versions.APIVersion("2.27"))
|
||||
self.assertFalse(self.mock_log.warning.called)
|
||||
|
||||
response = mock.MagicMock(headers={})
|
||||
api_versions.check_headers(response, api_versions.APIVersion("2.27"))
|
||||
self.assertTrue(self.mock_log.warning.called)
|
||||
|
||||
def test_microversion_is_not_specified(self):
|
||||
response = mock.MagicMock(headers={api_versions.HEADER_NAME: ""})
|
||||
response = mock.MagicMock(
|
||||
headers={api_versions.LEGACY_HEADER_NAME: ""})
|
||||
api_versions.check_headers(response, api_versions.APIVersion("2.2"))
|
||||
self.assertFalse(self.mock_log.warning.called)
|
||||
|
||||
|
@ -2776,6 +2776,9 @@ class ShellTest(utils.TestCase):
|
||||
# new microversion, just an additional checks. See
|
||||
# https://review.openstack.org/#/c/233076/ for more details)
|
||||
20, # doesn't require any changes in novaclient
|
||||
27, # NOTE(cdent): 27 adds support for updated microversion
|
||||
# headers, and is tested in test_api_versions, but is
|
||||
# not explicitly tested via wraps and _SUBSTITUTIONS.
|
||||
])
|
||||
versions_supported = set(range(0,
|
||||
novaclient.API_MAX_VERSION.ver_minor + 1))
|
||||
|
Loading…
Reference in New Issue
Block a user