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:
parent
fac7fc52eb
commit
3ed02db00e
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@ -37,6 +38,7 @@ from manila.share.drivers import helpers as driver_helpers
|
|||||||
|
|
||||||
rados = None
|
rados = None
|
||||||
json_command = None
|
json_command = None
|
||||||
|
ceph_default_target = None
|
||||||
|
|
||||||
|
|
||||||
def setup_rados():
|
def setup_rados():
|
||||||
@ -150,7 +152,7 @@ class RadosError(Exception):
|
|||||||
|
|
||||||
|
|
||||||
def rados_command(rados_client, prefix=None, args=None, json_obj=False,
|
def rados_command(rados_client, prefix=None, args=None, json_obj=False,
|
||||||
target=('mon-mgr', )):
|
target=None):
|
||||||
"""Safer wrapper for ceph_argparse.json_command
|
"""Safer wrapper for ceph_argparse.json_command
|
||||||
|
|
||||||
Raises error exception instead of relying on caller to check return
|
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
|
If json is False, return a decoded string (the data returned by
|
||||||
ceph command)
|
ceph command)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
target = target or ceph_default_target
|
||||||
|
|
||||||
if args is None:
|
if args is None:
|
||||||
args = {}
|
args = {}
|
||||||
|
|
||||||
@ -216,7 +221,7 @@ class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
|
|||||||
self._rados_client = None
|
self._rados_client = None
|
||||||
# name of the filesystem/volume used by the driver
|
# name of the filesystem/volume used by the driver
|
||||||
self._volname = None
|
self._volname = None
|
||||||
|
self._ceph_mon_version = None
|
||||||
self.configuration.append_config_values(cephfs_opts)
|
self.configuration.append_config_values(cephfs_opts)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -237,6 +242,8 @@ class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
|
|||||||
protocol_helper_class = getattr(
|
protocol_helper_class = getattr(
|
||||||
sys.modules[__name__], 'NFSProtocolHelper')
|
sys.modules[__name__], 'NFSProtocolHelper')
|
||||||
|
|
||||||
|
self.setup_default_ceph_cmd_target()
|
||||||
|
|
||||||
self.protocol_helper = protocol_helper_class(
|
self.protocol_helper = protocol_helper_class(
|
||||||
self._execute,
|
self._execute,
|
||||||
self.configuration,
|
self.configuration,
|
||||||
@ -312,6 +319,44 @@ class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
|
|||||||
|
|
||||||
return self.protocol_helper.get_export_locations(share, subvolume_path)
|
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
|
@property
|
||||||
def rados_client(self):
|
def rados_client(self):
|
||||||
if self._rados_client:
|
if self._rados_client:
|
||||||
|
@ -89,6 +89,8 @@ class CephFSDriverTestCase(test.TestCase):
|
|||||||
self.mock_object(driver, 'NativeProtocolHelper')
|
self.mock_object(driver, 'NativeProtocolHelper')
|
||||||
self.mock_object(driver, 'NFSProtocolHelper')
|
self.mock_object(driver, 'NFSProtocolHelper')
|
||||||
|
|
||||||
|
driver.ceph_default_target = ('mon-mgr', )
|
||||||
|
|
||||||
self._driver = (
|
self._driver = (
|
||||||
driver.CephFSDriver(execute=self._execute,
|
driver.CephFSDriver(execute=self._execute,
|
||||||
configuration=self.fake_conf))
|
configuration=self.fake_conf))
|
||||||
@ -121,6 +123,37 @@ class CephFSDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(DEFAULT_VOLUME_MODE, self._driver._cephfs_volume_mode)
|
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')
|
@ddt.data('cephfs', 'nfs')
|
||||||
def test_check_for_setup_error(self, protocol_helper):
|
def test_check_for_setup_error(self, protocol_helper):
|
||||||
self._driver.configuration.cephfs_protocol_helper_type = (
|
self._driver.configuration.cephfs_protocol_helper_type = (
|
||||||
@ -551,6 +584,8 @@ class NativeProtocolHelperTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.mock_object(driver, "rados_command")
|
self.mock_object(driver, "rados_command")
|
||||||
|
|
||||||
|
driver.ceph_default_target = ('mon-mgr', )
|
||||||
|
|
||||||
self._native_protocol_helper = driver.NativeProtocolHelper(
|
self._native_protocol_helper = driver.NativeProtocolHelper(
|
||||||
None,
|
None,
|
||||||
self.fake_conf,
|
self.fake_conf,
|
||||||
@ -851,6 +886,8 @@ class NFSProtocolHelperTestCase(test.TestCase):
|
|||||||
self.mock_object(driver.socket, 'gethostname')
|
self.mock_object(driver.socket, 'gethostname')
|
||||||
self.mock_object(driver, "rados_command")
|
self.mock_object(driver, "rados_command")
|
||||||
|
|
||||||
|
driver.ceph_default_target = ('mon-mgr', )
|
||||||
|
|
||||||
self._nfs_helper = driver.NFSProtocolHelper(
|
self._nfs_helper = driver.NFSProtocolHelper(
|
||||||
self._execute,
|
self._execute,
|
||||||
self.fake_conf,
|
self.fake_conf,
|
||||||
@ -1172,6 +1209,8 @@ class CephFSDriverAltConfigTestCase(test.TestCase):
|
|||||||
self.mock_object(driver, 'NativeProtocolHelper')
|
self.mock_object(driver, 'NativeProtocolHelper')
|
||||||
self.mock_object(driver, 'NFSProtocolHelper')
|
self.mock_object(driver, 'NFSProtocolHelper')
|
||||||
|
|
||||||
|
driver.ceph_default_target = ('mon-mgr', )
|
||||||
|
|
||||||
@ddt.data('cephfs', 'nfs')
|
@ddt.data('cephfs', 'nfs')
|
||||||
def test_do_setup_alt_volume_mode(self, protocol_helper):
|
def test_do_setup_alt_volume_mode(self, protocol_helper):
|
||||||
self.fake_conf.set_default('cephfs_volume_mode', ALT_VOLUME_MODE)
|
self.fake_conf.set_default('cephfs_volume_mode', ALT_VOLUME_MODE)
|
||||||
|
@ -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.
|
Loading…
Reference in New Issue
Block a user