UnsupportedVersion Thrown for Supported Version

If the maximum client version is higher than the maximum server version,
but the server version is otherwise valid, an UnsupportedVersion
exception is thrown. This bug fixes this issue by downgrading the
requested version, during API version discovery, from the maximum
client version to the maximum server version. The maximum server version
must be supported by the client. If all conditions are properly met the
client will continue to use the maximum server version for the remainder
of the request.

In order to log that the client version is being downgraded to match
the server version, when using the --debug flag, it was necessary to
update the logging configuration. Logging can now be used anywhere in
manilaclient as needed.

Change-Id: I96d273071966d2dc63de40c6f1b777fbb34a50fa
Closes-Bug: 1559290
This commit is contained in:
Chuck Fouts
2016-03-18 16:41:57 -04:00
parent 8fc8bd9eb2
commit 8143f7aa1c
3 changed files with 60 additions and 21 deletions

View File

@@ -25,11 +25,7 @@ from manilaclient.openstack.common._i18n import _
from manilaclient.openstack.common import cliutils
from manilaclient import utils
LOG = logging.getLogger(__name__)
if not LOG.handlers:
LOG.addHandler(logging.StreamHandler())
MAX_VERSION = '2.15'
MIN_VERSION = '2.0'
@@ -245,7 +241,8 @@ def discover_version(client, requested_version):
"""Discovers the most recent version for client and API.
Checks 'requested_version' and returns the most recent version
supported by both the API and the client.
supported by both the API and the client. If there is not a supported
version then an UnsupportedVersion exception is thrown.
:param client: client object
:param requested_version: requested version represented by APIVersion obj
@@ -256,14 +253,15 @@ def discover_version(client, requested_version):
valid_version = requested_version
if server_start_version.is_null() and server_end_version.is_null():
LOG.warning("Server does not support microversions. Changing server "
"version to %(min_version)s." %
{"min_version": DEPRECATED_VERSION})
msg = ("Server does not support microversions. Changing server "
"version to %(min_version)s.")
LOG.debug(msg, {"min_version": DEPRECATED_VERSION})
valid_version = APIVersion(DEPRECATED_VERSION)
else:
_validate_requested_version(requested_version,
server_start_version,
server_end_version)
valid_version = _validate_requested_version(
requested_version,
server_start_version,
server_end_version)
_validate_server_version(server_start_version, server_end_version)
return valid_version
@@ -275,18 +273,34 @@ def _validate_requested_version(requested_version,
"""Validates the requested version.
Checks 'requested_version' is within the min/max range supported by the
server.
server. If 'requested_version' is not within range then attempts to
downgrade to 'server_end_version'. Otherwise an UnsupportedVersion
exception is thrown.
:param requested_version: requestedversion represented by APIVersion obj
:param server_start_version: APIVersion object representing server min
:param server_end_version: APIVersion object representing server max
"""
valid_version = requested_version
if not requested_version.matches(server_start_version, server_end_version):
raise exceptions.UnsupportedVersion(
_("The specified version isn't supported by server. The valid "
"version range is '%(min)s' to '%(max)s'") % {
"min": server_start_version.get_string(),
"max": server_end_version.get_string()})
if server_end_version <= requested_version:
if (manilaclient.API_MIN_VERSION <= server_end_version and
server_end_version <= manilaclient.API_MAX_VERSION):
msg = _("Requested version %(requested_version)s is "
"not supported. Downgrading requested version "
"to %(server_end_version)s.")
LOG.debug(msg, {
"requested_version": requested_version,
"server_end_version": server_end_version})
valid_version = server_end_version
else:
raise exceptions.UnsupportedVersion(
_("The specified version isn't supported by server. The valid "
"version range is '%(min)s' to '%(max)s'") % {
"min": server_start_version.get_string(),
"max": server_end_version.get_string()})
return valid_version
def _validate_server_version(server_start_version, server_end_version):

View File

@@ -414,11 +414,11 @@ class OpenStackManilaShell(object):
if not debug:
return
streamhandler = logging.StreamHandler()
streamformat = "%(levelname)s (%(module)s:%(lineno)d) %(message)s"
streamhandler.setFormatter(logging.Formatter(streamformat))
logger.setLevel(logging.DEBUG)
logger.addHandler(streamhandler)
logging.basicConfig(level=logging.DEBUG, format=streamformat)
logging.getLogger('requests.packages.urllib3.connectionpool'
).setLevel(logging.WARNING)
logging.getLogger('keystoneclient.session').setLevel(logging.WARNING)
def _build_subcommands_and_extensions(self,
os_api_version,

View File

@@ -88,8 +88,14 @@ class APIVersionTestCase(utils.TestCase):
v8 = api_versions.APIVersion("4.0")
v_null = api_versions.APIVersion()
v1_25 = api_versions.APIVersion("2.5")
v1_32 = api_versions.APIVersion("3.32")
v1_33 = api_versions.APIVersion("3.33")
self.assertTrue(v2.matches(v1, v3))
self.assertTrue(v2.matches(v1, v_null))
self.assertTrue(v1_32.matches(v1_25, v1_33))
self.assertTrue(v1.matches(v6, v2))
self.assertTrue(v4.matches(v2, v7))
self.assertTrue(v4.matches(v_null, v7))
@@ -271,6 +277,25 @@ class DiscoverVersionTestCase(utils.TestCase):
api_versions.APIVersion("2.10"))
self.assertTrue(self.fake_client.services.server_api_version.called)
def test_requested_version_is_less_than_server_max(self):
self._mock_returned_server_version('2.17', '2.14')
max_version = api_versions.APIVersion('2.15')
manilaclient.API_MAX_VERSION = max_version
manilaclient.API_MIN_VERSION = api_versions.APIVersion('2.12')
version = api_versions.discover_version(self.fake_client, max_version)
self.assertEqual(api_versions.APIVersion('2.15'), version)
def test_requested_version_is_downgraded(self):
server_end_version = '2.7'
self._mock_returned_server_version(server_end_version, '2.0')
max_version = api_versions.APIVersion("2.8")
manilaclient.API_MAX_VERSION = max_version
manilaclient.API_MIN_VERSION = api_versions.APIVersion("2.5")
version = api_versions.discover_version(self.fake_client, max_version)
self.assertEqual(api_versions.APIVersion(server_end_version), version)
def test_server_and_client_max_are_same(self):
self._mock_returned_server_version('2.5', '2.0')
manilaclient.API_MAX_VERSION = api_versions.APIVersion("2.5")