Add Ceph version check

CephFS drivers in OpenStack Manila are directing
mgr commands to the mgr by specifying mon-mgr as
the target [0]. This target (mon-mgr) was added
to Ceph in Octopus [1].

We would need a version check in order to set the
correct target while we wait on the backport on Ceph
to land [2].

[0] 3ea5d50a23
[1] 4000d500c0
[2] https://tracker.ceph.com/issues/51039

Closes-Bug: #1930459
Change-Id: I1a1079df8e104c5ddba29cb614eb4e02a304082e
This commit is contained in:
Victoria Martinez de la Cruz 2021-06-02 16:37:06 +00:00
parent fac7fc52eb
commit 3ed02db00e
3 changed files with 93 additions and 2 deletions

View File

@ -16,6 +16,7 @@
import ipaddress
import json
import re
import socket
import sys
@ -37,6 +38,7 @@ from manila.share.drivers import helpers as driver_helpers
rados = None
json_command = None
ceph_default_target = None
def setup_rados():
@ -150,7 +152,7 @@ class RadosError(Exception):
def rados_command(rados_client, prefix=None, args=None, json_obj=False,
target=('mon-mgr', )):
target=None):
"""Safer wrapper for ceph_argparse.json_command
Raises error exception instead of relying on caller to check return
@ -166,6 +168,9 @@ def rados_command(rados_client, prefix=None, args=None, json_obj=False,
If json is False, return a decoded string (the data returned by
ceph command)
"""
target = target or ceph_default_target
if args is None:
args = {}
@ -216,7 +221,7 @@ class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
self._rados_client = None
# name of the filesystem/volume used by the driver
self._volname = None
self._ceph_mon_version = None
self.configuration.append_config_values(cephfs_opts)
try:
@ -237,6 +242,8 @@ class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
protocol_helper_class = getattr(
sys.modules[__name__], 'NFSProtocolHelper')
self.setup_default_ceph_cmd_target()
self.protocol_helper = protocol_helper_class(
self._execute,
self.configuration,
@ -312,6 +319,44 @@ class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
return self.protocol_helper.get_export_locations(share, subvolume_path)
def setup_default_ceph_cmd_target(self):
global ceph_default_target
if not ceph_default_target:
ceph_default_target = ('mon-mgr', )
try:
ceph_major_version = self.ceph_mon_version['major']
except Exception:
msg = _("Error reading ceph version to set the default "
"target. Please check your Ceph backend is reachable.")
raise exception.ShareBackendException(msg=msg)
if ceph_major_version == '14':
ceph_default_target = ('mgr', )
elif ceph_major_version < '14':
msg = _("CephFSDriver does not support Ceph "
"cluster version less than 14.x (Nautilus)")
raise exception.ShareBackendException(msg=msg)
@property
def ceph_mon_version(self):
if self._ceph_mon_version:
return self._ceph_mon_version
self._ceph_mon_version = {}
output = rados_command(self.rados_client, "version", target=('mon', ))
version_str = json.loads(output)["version"]
p = re.compile(r"ceph version (\d+)\.(\d+)\.(\d+)")
major, minor, extra = p.match(version_str).groups()
self._ceph_mon_version['major'] = major
self._ceph_mon_version['minor'] = minor
self._ceph_mon_version['extra'] = extra
return self._ceph_mon_version
@property
def rados_client(self):
if self._rados_client:

View File

@ -89,6 +89,8 @@ class CephFSDriverTestCase(test.TestCase):
self.mock_object(driver, 'NativeProtocolHelper')
self.mock_object(driver, 'NFSProtocolHelper')
driver.ceph_default_target = ('mon-mgr', )
self._driver = (
driver.CephFSDriver(execute=self._execute,
configuration=self.fake_conf))
@ -121,6 +123,37 @@ class CephFSDriverTestCase(test.TestCase):
self.assertEqual(DEFAULT_VOLUME_MODE, self._driver._cephfs_volume_mode)
@ddt.data(
('{"version": "ceph version 16.2.4"}', 'pacific'),
('{"version": "ceph version 15.1.2"}', 'octopus'),
('{"version": "ceph version 14.3.1"}', 'nautilus'),
)
@ddt.unpack
def test_version_check(self, ceph_mon_version, codename):
driver.ceph_default_target = None
driver.rados_command.return_value = ceph_mon_version
self._driver.do_setup(self._context)
if codename == 'nautilus':
self.assertEqual(('mgr', ), driver.ceph_default_target)
else:
self.assertEqual(('mon-mgr', ), driver.ceph_default_target)
driver.rados_command.assert_called_once_with(
self._driver.rados_client, "version", target=('mon', ))
self.assertEqual(1, driver.rados_command.call_count)
def test_version_check_not_supported(self):
driver.ceph_default_target = None
driver.rados_command.return_value = (
'{"version": "ceph version 13.0.1"}')
self.assertRaises(exception.ShareBackendException,
self._driver.do_setup,
self._context)
@ddt.data('cephfs', 'nfs')
def test_check_for_setup_error(self, protocol_helper):
self._driver.configuration.cephfs_protocol_helper_type = (
@ -551,6 +584,8 @@ class NativeProtocolHelperTestCase(test.TestCase):
self.mock_object(driver, "rados_command")
driver.ceph_default_target = ('mon-mgr', )
self._native_protocol_helper = driver.NativeProtocolHelper(
None,
self.fake_conf,
@ -851,6 +886,8 @@ class NFSProtocolHelperTestCase(test.TestCase):
self.mock_object(driver.socket, 'gethostname')
self.mock_object(driver, "rados_command")
driver.ceph_default_target = ('mon-mgr', )
self._nfs_helper = driver.NFSProtocolHelper(
self._execute,
self.fake_conf,
@ -1172,6 +1209,8 @@ class CephFSDriverAltConfigTestCase(test.TestCase):
self.mock_object(driver, 'NativeProtocolHelper')
self.mock_object(driver, 'NFSProtocolHelper')
driver.ceph_default_target = ('mon-mgr', )
@ddt.data('cephfs', 'nfs')
def test_do_setup_alt_volume_mode(self, protocol_helper):
self.fake_conf.set_default('cephfs_volume_mode', ALT_VOLUME_MODE)

View File

@ -0,0 +1,7 @@
---
fixes:
- |
A Ceph version check has been added as part of this change to address
the absense of the mon-mgr target in Ceph Nautilus. With this change,
Ceph Nautilus users can leverage their storage backend with the
OpenStack manila Wallaby release.