Set mode for CephFS volumes and snapshots
Corresponding ceph_volume_client PR [1]
[1] https://github.com/ceph/ceph/pull/24839
Depends-on: https://review.openstack.org/#/c/634028/
Change-Id: Iad78b8cc25c34d3675cd38ce9c757ad0e411b613
(cherry picked from commit 721bb70a81
)
This commit is contained in:
parent
89ecc48698
commit
4831c624ee
@ -42,6 +42,8 @@ CEPHX_ACCESS_TYPE = "cephx"
|
|||||||
# The default Ceph administrative identity
|
# The default Ceph administrative identity
|
||||||
CEPH_DEFAULT_AUTH_ID = "admin"
|
CEPH_DEFAULT_AUTH_ID = "admin"
|
||||||
|
|
||||||
|
DEFAULT_VOLUME_MODE = '755'
|
||||||
|
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
@ -89,6 +91,11 @@ cephfs_opts = [
|
|||||||
help="The password to authenticate as the user in the remote "
|
help="The password to authenticate as the user in the remote "
|
||||||
"Ganesha server host. This is not required if "
|
"Ganesha server host. This is not required if "
|
||||||
"'cephfs_ganesha_path_to_private_key' is configured."),
|
"'cephfs_ganesha_path_to_private_key' is configured."),
|
||||||
|
cfg.StrOpt('cephfs_volume_mode',
|
||||||
|
default=DEFAULT_VOLUME_MODE,
|
||||||
|
help="The read/write/execute permissions mode for CephFS "
|
||||||
|
"volumes, snapshots, and snapshot groups expressed in "
|
||||||
|
"Octal as with linux 'chmod' or 'umask' commands."),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -115,6 +122,14 @@ class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
|
|||||||
|
|
||||||
self.configuration.append_config_values(cephfs_opts)
|
self.configuration.append_config_values(cephfs_opts)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._cephfs_volume_mode = int(
|
||||||
|
self.configuration.cephfs_volume_mode, 8)
|
||||||
|
except ValueError:
|
||||||
|
msg = _("Invalid CephFS volume mode %s")
|
||||||
|
raise exception.BadConfigurationException(
|
||||||
|
msg % self.configuration.cephfs_volume_mode)
|
||||||
|
|
||||||
def do_setup(self, context):
|
def do_setup(self, context):
|
||||||
if self.configuration.cephfs_protocol_helper_type.upper() == "CEPHFS":
|
if self.configuration.cephfs_protocol_helper_type.upper() == "CEPHFS":
|
||||||
protocol_helper_class = getattr(
|
protocol_helper_class = getattr(
|
||||||
@ -237,7 +252,8 @@ class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
|
|||||||
|
|
||||||
# Create the CephFS volume
|
# Create the CephFS volume
|
||||||
cephfs_volume = self.volume_client.create_volume(
|
cephfs_volume = self.volume_client.create_volume(
|
||||||
cephfs_share_path(share), size=size, data_isolated=data_isolated)
|
cephfs_share_path(share), size=size, data_isolated=data_isolated,
|
||||||
|
mode=self._cephfs_volume_mode)
|
||||||
|
|
||||||
return self.protocol_helper.get_export_locations(share, cephfs_volume)
|
return self.protocol_helper.get_export_locations(share, cephfs_volume)
|
||||||
|
|
||||||
@ -284,7 +300,8 @@ class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
|
|||||||
def create_snapshot(self, context, snapshot, share_server=None):
|
def create_snapshot(self, context, snapshot, share_server=None):
|
||||||
self.volume_client.create_snapshot_volume(
|
self.volume_client.create_snapshot_volume(
|
||||||
cephfs_share_path(snapshot['share']),
|
cephfs_share_path(snapshot['share']),
|
||||||
'_'.join([snapshot['snapshot_id'], snapshot['id']]))
|
'_'.join([snapshot['snapshot_id'], snapshot['id']]),
|
||||||
|
mode=self._cephfs_volume_mode)
|
||||||
|
|
||||||
def delete_snapshot(self, context, snapshot, share_server=None):
|
def delete_snapshot(self, context, snapshot, share_server=None):
|
||||||
self.volume_client.destroy_snapshot_volume(
|
self.volume_client.destroy_snapshot_volume(
|
||||||
@ -292,7 +309,8 @@ class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
|
|||||||
'_'.join([snapshot['snapshot_id'], snapshot['id']]))
|
'_'.join([snapshot['snapshot_id'], snapshot['id']]))
|
||||||
|
|
||||||
def create_share_group(self, context, sg_dict, share_server=None):
|
def create_share_group(self, context, sg_dict, share_server=None):
|
||||||
self.volume_client.create_group(sg_dict['id'])
|
self.volume_client.create_group(sg_dict['id'],
|
||||||
|
mode=self._cephfs_volume_mode)
|
||||||
|
|
||||||
def delete_share_group(self, context, sg_dict, share_server=None):
|
def delete_share_group(self, context, sg_dict, share_server=None):
|
||||||
self.volume_client.destroy_group(sg_dict['id'])
|
self.volume_client.destroy_group(sg_dict['id'])
|
||||||
@ -309,7 +327,8 @@ class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
|
|||||||
share_server=None):
|
share_server=None):
|
||||||
self.volume_client.create_snapshot_group(
|
self.volume_client.create_snapshot_group(
|
||||||
snap_dict['share_group_id'],
|
snap_dict['share_group_id'],
|
||||||
snap_dict['id'])
|
snap_dict['id'],
|
||||||
|
mode=self._cephfs_volume_mode)
|
||||||
|
|
||||||
return None, []
|
return None, []
|
||||||
|
|
||||||
|
@ -29,6 +29,11 @@ from manila import test
|
|||||||
from manila.tests import fake_share
|
from manila.tests import fake_share
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_VOLUME_MODE = 0o755
|
||||||
|
ALT_VOLUME_MODE_CFG = '775'
|
||||||
|
ALT_VOLUME_MODE = 0o775
|
||||||
|
|
||||||
|
|
||||||
class MockVolumeClientModule(object):
|
class MockVolumeClientModule(object):
|
||||||
"""Mocked up version of ceph's VolumeClient interface."""
|
"""Mocked up version of ceph's VolumeClient interface."""
|
||||||
|
|
||||||
@ -129,6 +134,8 @@ class CephFSDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
self._driver.protocol_helper.init_helper.assert_called_once_with()
|
self._driver.protocol_helper.init_helper.assert_called_once_with()
|
||||||
|
|
||||||
|
self.assertEqual(DEFAULT_VOLUME_MODE, self._driver._cephfs_volume_mode)
|
||||||
|
|
||||||
def test_create_share(self):
|
def test_create_share(self):
|
||||||
cephfs_volume = {"mount_path": "/foo/bar"}
|
cephfs_volume = {"mount_path": "/foo/bar"}
|
||||||
|
|
||||||
@ -137,7 +144,7 @@ class CephFSDriverTestCase(test.TestCase):
|
|||||||
self._driver._volume_client.create_volume.assert_called_once_with(
|
self._driver._volume_client.create_volume.assert_called_once_with(
|
||||||
driver.cephfs_share_path(self._share),
|
driver.cephfs_share_path(self._share),
|
||||||
size=self._share['size'] * units.Gi,
|
size=self._share['size'] * units.Gi,
|
||||||
data_isolated=False)
|
data_isolated=False, mode=DEFAULT_VOLUME_MODE)
|
||||||
(self._driver.protocol_helper.get_export_locations.
|
(self._driver.protocol_helper.get_export_locations.
|
||||||
assert_called_once_with(self._share, cephfs_volume))
|
assert_called_once_with(self._share, cephfs_volume))
|
||||||
|
|
||||||
@ -175,7 +182,8 @@ class CephFSDriverTestCase(test.TestCase):
|
|||||||
self._driver._volume_client.create_volume.assert_called_once_with(
|
self._driver._volume_client.create_volume.assert_called_once_with(
|
||||||
driver.cephfs_share_path(self._share),
|
driver.cephfs_share_path(self._share),
|
||||||
size=self._share['size'] * units.Gi,
|
size=self._share['size'] * units.Gi,
|
||||||
data_isolated=False)
|
data_isolated=False,
|
||||||
|
mode=DEFAULT_VOLUME_MODE)
|
||||||
|
|
||||||
def test_create_data_isolated(self):
|
def test_create_data_isolated(self):
|
||||||
self.mock_object(share_types, 'get_share_type_extra_specs',
|
self.mock_object(share_types, 'get_share_type_extra_specs',
|
||||||
@ -187,7 +195,8 @@ class CephFSDriverTestCase(test.TestCase):
|
|||||||
self._driver._volume_client.create_volume.assert_called_once_with(
|
self._driver._volume_client.create_volume.assert_called_once_with(
|
||||||
driver.cephfs_share_path(self._share),
|
driver.cephfs_share_path(self._share),
|
||||||
size=self._share['size'] * units.Gi,
|
size=self._share['size'] * units.Gi,
|
||||||
data_isolated=True)
|
data_isolated=True,
|
||||||
|
mode=DEFAULT_VOLUME_MODE)
|
||||||
|
|
||||||
def test_delete_share(self):
|
def test_delete_share(self):
|
||||||
self._driver.delete_share(self._context, self._share)
|
self._driver.delete_share(self._context, self._share)
|
||||||
@ -260,7 +269,8 @@ class CephFSDriverTestCase(test.TestCase):
|
|||||||
(self._driver._volume_client.create_snapshot_volume
|
(self._driver._volume_client.create_snapshot_volume
|
||||||
.assert_called_once_with(
|
.assert_called_once_with(
|
||||||
driver.cephfs_share_path(self._share),
|
driver.cephfs_share_path(self._share),
|
||||||
"snappy1_instance1"))
|
"snappy1_instance1",
|
||||||
|
mode=DEFAULT_VOLUME_MODE))
|
||||||
|
|
||||||
def test_delete_snapshot(self):
|
def test_delete_snapshot(self):
|
||||||
self._driver.delete_snapshot(self._context,
|
self._driver.delete_snapshot(self._context,
|
||||||
@ -280,7 +290,7 @@ class CephFSDriverTestCase(test.TestCase):
|
|||||||
self._driver.create_share_group(self._context, {"id": "grp1"}, None)
|
self._driver.create_share_group(self._context, {"id": "grp1"}, None)
|
||||||
|
|
||||||
self._driver._volume_client.create_group.assert_called_once_with(
|
self._driver._volume_client.create_group.assert_called_once_with(
|
||||||
"grp1")
|
"grp1", mode=DEFAULT_VOLUME_MODE)
|
||||||
|
|
||||||
def test_delete_share_group(self):
|
def test_delete_share_group(self):
|
||||||
self._driver.delete_share_group(self._context, {"id": "grp1"}, None)
|
self._driver.delete_share_group(self._context, {"id": "grp1"}, None)
|
||||||
@ -291,16 +301,16 @@ class CephFSDriverTestCase(test.TestCase):
|
|||||||
def test_create_share_snapshot(self):
|
def test_create_share_snapshot(self):
|
||||||
self._driver.create_share_group_snapshot(self._context, {
|
self._driver.create_share_group_snapshot(self._context, {
|
||||||
'share_group_id': 'sgid',
|
'share_group_id': 'sgid',
|
||||||
'id': 'snapid'
|
'id': 'snapid',
|
||||||
})
|
})
|
||||||
|
|
||||||
(self._driver._volume_client.create_snapshot_group.
|
(self._driver._volume_client.create_snapshot_group.
|
||||||
assert_called_once_with("sgid", "snapid"))
|
assert_called_once_with("sgid", "snapid", mode=DEFAULT_VOLUME_MODE))
|
||||||
|
|
||||||
def test_delete_share_group_snapshot(self):
|
def test_delete_share_group_snapshot(self):
|
||||||
self._driver.delete_share_group_snapshot(self._context, {
|
self._driver.delete_share_group_snapshot(self._context, {
|
||||||
'share_group_id': 'sgid',
|
'share_group_id': 'sgid',
|
||||||
'id': 'snapid'
|
'id': 'snapid',
|
||||||
})
|
})
|
||||||
|
|
||||||
(self._driver._volume_client.destroy_snapshot_group.
|
(self._driver._volume_client.destroy_snapshot_group.
|
||||||
@ -676,3 +686,59 @@ class NFSProtocolHelperTestCase(test.TestCase):
|
|||||||
self._volume_client._get_path.assert_called_once_with(
|
self._volume_client._get_path.assert_called_once_with(
|
||||||
'fakevolumepath')
|
'fakevolumepath')
|
||||||
self.assertEqual('/foo/bar', ret)
|
self.assertEqual('/foo/bar', ret)
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class CephFSDriverAltConfigTestCase(test.TestCase):
|
||||||
|
"""Test the CephFS driver with non-default config values."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(CephFSDriverAltConfigTestCase, self).setUp()
|
||||||
|
self._execute = mock.Mock()
|
||||||
|
self.fake_conf = configuration.Configuration(None)
|
||||||
|
self._context = context.get_admin_context()
|
||||||
|
self._share = fake_share.fake_share(share_proto='CEPHFS')
|
||||||
|
|
||||||
|
self.fake_conf.set_default('driver_handles_share_servers', False)
|
||||||
|
self.fake_conf.set_default('cephfs_auth_id', 'manila')
|
||||||
|
|
||||||
|
self.mock_object(driver, "ceph_volume_client",
|
||||||
|
MockVolumeClientModule)
|
||||||
|
self.mock_object(driver, "ceph_module_found", True)
|
||||||
|
self.mock_object(driver, "cephfs_share_path")
|
||||||
|
self.mock_object(driver, 'NativeProtocolHelper')
|
||||||
|
self.mock_object(driver, 'NFSProtocolHelper')
|
||||||
|
|
||||||
|
@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_CFG)
|
||||||
|
self._driver = driver.CephFSDriver(execute=self._execute,
|
||||||
|
configuration=self.fake_conf)
|
||||||
|
|
||||||
|
self._driver.configuration.cephfs_protocol_helper_type = (
|
||||||
|
protocol_helper)
|
||||||
|
|
||||||
|
self._driver.do_setup(self._context)
|
||||||
|
|
||||||
|
if protocol_helper == 'cephfs':
|
||||||
|
driver.NativeProtocolHelper.assert_called_once_with(
|
||||||
|
self._execute, self._driver.configuration,
|
||||||
|
ceph_vol_client=self._driver._volume_client)
|
||||||
|
else:
|
||||||
|
driver.NFSProtocolHelper.assert_called_once_with(
|
||||||
|
self._execute, self._driver.configuration,
|
||||||
|
ceph_vol_client=self._driver._volume_client)
|
||||||
|
|
||||||
|
self._driver.protocol_helper.init_helper.assert_called_once_with()
|
||||||
|
|
||||||
|
self.assertEqual(ALT_VOLUME_MODE, self._driver._cephfs_volume_mode)
|
||||||
|
|
||||||
|
@ddt.data('0o759', '0x755', '12a3')
|
||||||
|
def test_volume_mode_exception(self, volume_mode):
|
||||||
|
# cephfs_volume_mode must be a string representing an int as octal
|
||||||
|
self.fake_conf.set_default('cephfs_volume_mode', volume_mode)
|
||||||
|
|
||||||
|
self.assertRaises(exception.BadConfigurationException,
|
||||||
|
driver.CephFSDriver, execute=self._execute,
|
||||||
|
configuration=self.fake_conf)
|
||||||
|
8
releasenotes/notes/cephfs-set-mode-b7fb3ec51300c220.yaml
Normal file
8
releasenotes/notes/cephfs-set-mode-b7fb3ec51300c220.yaml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Shares backed by CephFS no longer have hard-coded mode 755. Use
|
||||||
|
the ``cephfs_volume_mode`` configuration option to set another
|
||||||
|
mode, such as 775 when using manila dynamic external storage
|
||||||
|
provider with OpenShift. The default value remains 755 for
|
||||||
|
backwards compatibility.
|
Loading…
Reference in New Issue
Block a user