diff --git a/nova/cmd/status.py b/nova/cmd/status.py index 1137905fa200..226d7b19f76a 100644 --- a/nova/cmd/status.py +++ b/nova/cmd/status.py @@ -28,6 +28,7 @@ import traceback from keystoneauth1 import exceptions as ks_exc from keystoneauth1 import loading as keystone from oslo_config import cfg +import pkg_resources import prettytable from sqlalchemy import func as sqlfunc from sqlalchemy import MetaData, Table, select @@ -200,10 +201,11 @@ class UpgradeCommands(object): """ try: versions = self._placement_get("/") - max_version = float(versions["versions"][0]["max_version"]) + max_version = pkg_resources.parse_version( + versions["versions"][0]["max_version"]) # NOTE(rpodolyaka): 1.4 is needed in Pike and further as # FilterScheduler will no longer fall back to not using placement - needs_version = 1.4 + needs_version = pkg_resources.parse_version("1.4") if max_version < needs_version: msg = (_('Placement API version %(needed)s needed, ' 'you have %(current)s.') % diff --git a/nova/tests/unit/cmd/test_status.py b/nova/tests/unit/cmd/test_status.py index 1d0a0784170c..71156abfcbcb 100644 --- a/nova/tests/unit/cmd/test_status.py +++ b/nova/tests/unit/cmd/test_status.py @@ -218,6 +218,26 @@ class TestPlacementCheck(test.NoDBTestCase): res = self.cmd._check_placement() self.assertEqual(status.UpgradeCheckCode.SUCCESS, res.code) + @mock.patch.object(status.UpgradeCommands, "_placement_get") + def test_version_comparison_does_not_use_floats(self, get): + # NOTE(rpodolyaka): previously _check_placement() coerced the version + # numbers to floats prior to comparison, that would lead to failures + # in cases like float('1.10') < float('1.4'). As we require 1.4+ now, + # the _check_placement() call below will assert that version comparison + # continues to work correctly when Placement API versions 1.10 + # (or newer) is released + get.return_value = { + "versions": [ + { + "min_version": "1.0", + "max_version": "1.10", + "id": "v1.0" + } + ] + } + res = self.cmd._check_placement() + self.assertEqual(status.UpgradeCheckCode.SUCCESS, res.code) + @mock.patch.object(status.UpgradeCommands, "_placement_get") def test_invalid_version(self, get): get.return_value = {