From 270d5d351e1f1a3ac27aa91ff7ec756b672401df Mon Sep 17 00:00:00 2001 From: Matt Riedemann Date: Wed, 3 Apr 2019 18:48:34 -0400 Subject: [PATCH] Add nova-status upgrade check for minimum required cinder API version The compute API has required cinder API >= 3.44 since Queens [1] for working with the volume attachments API as part of the wider volume multi-attach support. In order to start removing the compatibility code in the compute API this change adds an upgrade check for the minimum required cinder API version (3.44). [1] Ifc01dbf98545104c998ab96f65ff8623a6db0f28 Change-Id: Ic9d1fb364e06e08250c7c5d7d4bdb956cb60e678 --- doc/source/cli/nova-status.rst | 3 ++ nova/cmd/status.py | 37 +++++++++++++++++ nova/tests/unit/cmd/test_status.py | 40 +++++++++++++++++++ ...-require-cinder-3.44-6965b902dd230413.yaml | 6 +++ 4 files changed, 86 insertions(+) create mode 100644 releasenotes/notes/train-require-cinder-3.44-6965b902dd230413.yaml diff --git a/doc/source/cli/nova-status.rst b/doc/source/cli/nova-status.rst index 54c14ef701ba..b3c3b31b87a6 100644 --- a/doc/source/cli/nova-status.rst +++ b/doc/source/cli/nova-status.rst @@ -133,6 +133,9 @@ Upgrade **20.0.0 (Train)** * Checks for the Placement API are modified to require version 1.31. + * Checks to ensure block-storage (cinder) API version 3.44 is + available in order to support multi-attach volumes. + If ``[cinder]/auth_type`` is not configured this is a no-op check. See Also ======== diff --git a/nova/cmd/status.py b/nova/cmd/status.py index 5301dd8979cc..242cbbbbc372 100644 --- a/nova/cmd/status.py +++ b/nova/cmd/status.py @@ -28,6 +28,7 @@ from oslo_config import cfg from oslo_serialization import jsonutils from oslo_upgradecheck import upgradecheck import pkg_resources +import six from sqlalchemy import func as sqlfunc from sqlalchemy import MetaData, Table, and_, select from sqlalchemy.sql import false @@ -37,10 +38,12 @@ import nova.conf from nova import config from nova import context as nova_context from nova.db.sqlalchemy import api as db_session +from nova import exception from nova.i18n import _ from nova.objects import cell_mapping as cell_mapping_obj from nova import utils from nova import version +from nova.volume import cinder CONF = nova.conf.CONF @@ -50,6 +53,10 @@ CONF = nova.conf.CONF # section in the nova-status man page (doc/source/cli/nova-status). MIN_PLACEMENT_MICROVERSION = "1.31" +# NOTE(mriedem): 3.44 is needed to work with volume attachment records which +# are required for supporting multi-attach capable volumes. +MIN_CINDER_MICROVERSION = '3.44' + class UpgradeCommands(upgradecheck.UpgradeCommands): """Commands related to upgrades. @@ -456,6 +463,34 @@ class UpgradeCommands(upgradecheck.UpgradeCommands): return upgradecheck.Result(upgradecheck.Code.SUCCESS) + def _check_cinder(self): + """Checks to see that the cinder API is available at a given minimum + microversion. + """ + # Check to see if nova is even configured for Cinder yet (fresh install + # or maybe not using Cinder at all). + if CONF.cinder.auth_type is None: + return upgradecheck.Result(upgradecheck.Code.SUCCESS) + + try: + # TODO(mriedem): Eventually use get_ksa_adapter here when it + # supports cinder. + cinder.is_microversion_supported( + nova_context.get_admin_context(), MIN_CINDER_MICROVERSION) + except exception.CinderAPIVersionNotAvailable: + return upgradecheck.Result( + upgradecheck.Code.FAILURE, + _('Cinder API %s or greater is required. Deploy at least ' + 'Cinder 12.0.0 (Queens).') % MIN_CINDER_MICROVERSION) + except Exception as ex: + # Anything else trying to connect, like bad config, is out of our + # hands so just return a warning. + return upgradecheck.Result( + upgradecheck.Code.WARNING, + _('Unable to determine Cinder API version due to error: %s') % + six.text_type(ex)) + return upgradecheck.Result(upgradecheck.Code.SUCCESS) + # The format of the check functions is to return an upgradecheck.Result # object with the appropriate upgradecheck.Code and details set. If the # check hits warnings or failures then those should be stored in the @@ -474,6 +509,8 @@ class UpgradeCommands(upgradecheck.UpgradeCommands): (_('Request Spec Migration'), _check_request_spec_migration), # Added in Stein (but also useful going back to Rocky) (_('Console Auths'), _check_console_auths), + # Added in Train + (_('Cinder API'), _check_cinder), ) diff --git a/nova/tests/unit/cmd/test_status.py b/nova/tests/unit/cmd/test_status.py index bf92ae676f78..0d821d7b8416 100644 --- a/nova/tests/unit/cmd/test_status.py +++ b/nova/tests/unit/cmd/test_status.py @@ -35,6 +35,7 @@ from requests import models from nova.cmd import status import nova.conf from nova import context +from nova import exception # NOTE(mriedem): We only use objects as a convenience to populate the database # in the tests, we don't use them in the actual CLI. from nova import objects @@ -780,3 +781,42 @@ class TestUpgradeCheckConsoles(test.NoDBTestCase): "host if you are performing a rolling upgrade to enable " "consoles to function during a partial upgrade.", result.details) + + +class TestUpgradeCheckCinderAPI(test.NoDBTestCase): + + def setUp(self): + super(TestUpgradeCheckCinderAPI, self).setUp() + self.cmd = status.UpgradeCommands() + + def test_cinder_not_configured(self): + self.flags(auth_type=None, group='cinder') + self.assertEqual(upgradecheck.Code.SUCCESS, + self.cmd._check_cinder().code) + + @mock.patch('nova.volume.cinder.is_microversion_supported', + side_effect=exception.CinderAPIVersionNotAvailable( + version='3.44')) + def test_microversion_not_available(self, mock_version_check): + self.flags(auth_type='password', group='cinder') + result = self.cmd._check_cinder() + mock_version_check.assert_called_once() + self.assertEqual(upgradecheck.Code.FAILURE, result.code) + self.assertIn('Cinder API 3.44 or greater is required.', + result.details) + + @mock.patch('nova.volume.cinder.is_microversion_supported', + side_effect=test.TestingException('oops')) + def test_unknown_error(self, mock_version_check): + self.flags(auth_type='password', group='cinder') + result = self.cmd._check_cinder() + mock_version_check.assert_called_once() + self.assertEqual(upgradecheck.Code.WARNING, result.code) + self.assertIn('oops', result.details) + + @mock.patch('nova.volume.cinder.is_microversion_supported') + def test_microversion_available(self, mock_version_check): + self.flags(auth_type='password', group='cinder') + result = self.cmd._check_cinder() + mock_version_check.assert_called_once() + self.assertEqual(upgradecheck.Code.SUCCESS, result.code) diff --git a/releasenotes/notes/train-require-cinder-3.44-6965b902dd230413.yaml b/releasenotes/notes/train-require-cinder-3.44-6965b902dd230413.yaml new file mode 100644 index 000000000000..85d9a0e2a116 --- /dev/null +++ b/releasenotes/notes/train-require-cinder-3.44-6965b902dd230413.yaml @@ -0,0 +1,6 @@ +--- +upgrade: + - | + The block-storage (cinder) version 3.44 API is now required when working + with volume attachments. A check has been added to the + ``nova-status upgrade check`` command for this requirement.