diff --git a/ironicclient/common/http.py b/ironicclient/common/http.py index 9cad35560..32929e3f3 100644 --- a/ironicclient/common/http.py +++ b/ironicclient/common/http.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -from distutils.version import StrictVersion import functools from http import client as http_client import json @@ -48,17 +47,36 @@ _MAJOR_VERSION = 1 API_VERSION = '/v%d' % _MAJOR_VERSION API_VERSION_SELECTED_STATES = ('user', 'negotiated', 'cached', 'default') - DEFAULT_MAX_RETRIES = 5 DEFAULT_RETRY_INTERVAL = 2 SENSITIVE_HEADERS = ('X-Auth-Token',) - SUPPORTED_ENDPOINT_SCHEME = ('http', 'https') _API_VERSION_RE = re.compile(r'/+(v%d)?/*$' % _MAJOR_VERSION) +@functools.total_ordering +class _Version: + _version_re = re.compile(r'^(\d) \. (\d+)$', re.VERBOSE | re.ASCII) + + def __init__(self, version): + match = self._version_re.match(version) + if not match: + raise ValueError('invalid version number %s' % version) + major, minor = match.group(1, 2) + self.version = (int(major), int(minor)) + + def __str__(self): + return '.'.join(str(v) for v in self.version) + + def __eq__(self, other): + return self.version == other.version + + def __lt__(self, other): + return self.version < other.version + + def _trim_endpoint_api_version(url): """Trim API version and trailing slash from endpoint.""" return re.sub(_API_VERSION_RE, '', url) @@ -159,7 +177,8 @@ class VersionNegotiationMixin(object): resp = _query_server(conn) min_ver, max_ver = self._parse_version_headers(resp) # Reset the maximum version that we permit - if StrictVersion(max_ver) > StrictVersion(LATEST_VERSION): + + if _Version(max_ver) > _Version(LATEST_VERSION): LOG.debug("Remote API version %(max_ver)s is greater than the " "version supported by ironicclient. Maximum available " "version is %(client_ver)s", @@ -198,8 +217,8 @@ class VersionNegotiationMixin(object): negotiated_ver = max_ver else: negotiated_ver = str( - min(StrictVersion(requested_version), - StrictVersion(max_ver))) + min(_Version(requested_version), _Version(max_ver)) + ) elif isinstance(requested_version, list): if 'latest' in requested_version: @@ -212,8 +231,8 @@ class VersionNegotiationMixin(object): versions = [] for version in requested_version: - if min_ver <= StrictVersion(version) <= max_ver: - versions.append(StrictVersion(version)) + if _Version(min_ver) <= _Version(version) <= _Version(max_ver): + versions.append(_Version(version)) if versions: negotiated_ver = str(max(versions)) else: @@ -232,8 +251,9 @@ class VersionNegotiationMixin(object): "or a list of string values representing API versions.") % {'req': requested_version})) - if StrictVersion(negotiated_ver) < StrictVersion(min_ver): + if _Version(negotiated_ver) < _Version(min_ver): negotiated_ver = min_ver + # server handles microversions, but doesn't support # the requested version, so try a negotiated version self.api_version_select_state = 'negotiated' @@ -248,10 +268,8 @@ class VersionNegotiationMixin(object): return negotiated_ver def _generic_parse_version_headers(self, accessor_func): - min_ver = accessor_func('X-OpenStack-Ironic-API-Minimum-Version', - None) - max_ver = accessor_func('X-OpenStack-Ironic-API-Maximum-Version', - None) + min_ver = accessor_func('X-OpenStack-Ironic-API-Minimum-Version', None) + max_ver = accessor_func('X-OpenStack-Ironic-API-Maximum-Version', None) return min_ver, max_ver def _parse_version_headers(self, accessor_func): diff --git a/ironicclient/tests/unit/common/test_http.py b/ironicclient/tests/unit/common/test_http.py index dd105a0e5..b892f0356 100644 --- a/ironicclient/tests/unit/common/test_http.py +++ b/ironicclient/tests/unit/common/test_http.py @@ -232,7 +232,7 @@ class VersionNegotiationMixinTest(utils.BaseTestCase): mock_conn = mock.MagicMock() self.test_object.api_version_select_state = 'user' self.test_object.os_ironic_api_version = ['1.1', '1.6', '1.25', - '1.26', '1.26.1', '1.27', + '1.26', '1.27', '1.28', '1.30'] result = self.test_object.negotiate_version(mock_conn, self.response) self.assertEqual('1.26', result)