From: Ramana Raja Date: Sun, 23 Jun 2019 12:09:36 +0000 (+0530) Subject: mgr/volumes: allow setting mode X-Git-Tag: v15.1.0~2360^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5c00cc30a1ad49b01e4ab84a17b62def88fc83c4;p=ceph.git mgr/volumes: allow setting mode ... of fs subvolumes and subvolume groups during their creation. Fixes: https://tracker.ceph.com/issues/40299 Signed-off-by: Ramana Raja --- diff --git a/qa/tasks/cephfs/test_volumes.py b/qa/tasks/cephfs/test_volumes.py index 19dce198aa74..11857a75a3a6 100644 --- a/qa/tasks/cephfs/test_volumes.py +++ b/qa/tasks/cephfs/test_volumes.py @@ -1,3 +1,4 @@ +import os import json import errno import random @@ -194,6 +195,65 @@ class TestVolumes(CephFSTestCase): self._fs_cmd("subvolume", "rm", self.volname, subvol1, group) self._fs_cmd("subvolumegroup", "rm", self.volname, group) + def test_subvolume_group_create_with_desired_mode(self): + group1 = self._generate_random_group_name() + group2 = self._generate_random_group_name() + # default mode + expected_mode1 = "755" + # desired mode + expected_mode2 = "777" + + # create group + self._fs_cmd("subvolumegroup", "create", self.volname, group1) + self._fs_cmd("subvolumegroup", "create", self.volname, group2, "--mode", "777") + + group1_path = os.path.join('volumes', group1) + group2_path = os.path.join('volumes', group2) + + # check group's mode + actual_mode1 = self.mount_a.run_shell(['stat', '-c' '%a', group1_path]).stdout.getvalue().strip() + actual_mode2 = self.mount_a.run_shell(['stat', '-c' '%a', group2_path]).stdout.getvalue().strip() + self.assertEqual(actual_mode1, expected_mode1) + self.assertEqual(actual_mode2, expected_mode2) + + self._fs_cmd("subvolumegroup", "rm", self.volname, group1) + self._fs_cmd("subvolumegroup", "rm", self.volname, group2) + + def test_subvolume_create_with_desired_mode_in_group(self): + subvol1 = self._generate_random_subvolume_name() + subvol2 = self._generate_random_subvolume_name() + subvol3 = self._generate_random_subvolume_name() + group = self._generate_random_group_name() + # default mode + expected_mode1 = "755" + # desired mode + expected_mode2 = "777" + + # create group + self._fs_cmd("subvolumegroup", "create", self.volname, group) + + # create subvolume in group + self._fs_cmd("subvolume", "create", self.volname, subvol1, "--group_name", group) + self._fs_cmd("subvolume", "create", self.volname, subvol2, "--group_name", group, "--mode", "777") + # check whether mode 0777 also works + self._fs_cmd("subvolume", "create", self.volname, subvol3, "--group_name", group, "--mode", "0777") + + subvol1_path = self._get_subvolume_path(self.volname, subvol1, group_name=group) + subvol2_path = self._get_subvolume_path(self.volname, subvol2, group_name=group) + subvol3_path = self._get_subvolume_path(self.volname, subvol3, group_name=group) + + # check subvolume's mode + actual_mode1 = self.mount_a.run_shell(['stat', '-c' '%a', subvol1_path]).stdout.getvalue().strip() + actual_mode2 = self.mount_a.run_shell(['stat', '-c' '%a', subvol2_path]).stdout.getvalue().strip() + actual_mode3 = self.mount_a.run_shell(['stat', '-c' '%a', subvol3_path]).stdout.getvalue().strip() + self.assertEqual(actual_mode1, expected_mode1) + self.assertEqual(actual_mode2, expected_mode2) + self.assertEqual(actual_mode3, expected_mode2) + + self._fs_cmd("subvolume", "rm", self.volname, subvol2, group) + self._fs_cmd("subvolume", "rm", self.volname, subvol1, group) + self._fs_cmd("subvolumegroup", "rm", self.volname, group) + def test_nonexistent_subvolme_group_rm(self): group = "non_existent_group" diff --git a/src/pybind/mgr/volumes/fs/volume.py b/src/pybind/mgr/volumes/fs/volume.py index 63ff2f834ddf..8cc7ef26fa05 100644 --- a/src/pybind/mgr/volumes/fs/volume.py +++ b/src/pybind/mgr/volumes/fs/volume.py @@ -169,9 +169,16 @@ class VolumeClient(object): # at the time of subvolume, snapshot and other create operations). return spec.is_default_group() or sv.get_group_path(spec) + @staticmethod + def octal_str_to_decimal_int(mode): + try: + return int(mode, 8) + except ValueError: + raise VolumeException(-errno.EINVAL, "Invalid mode '{0}'".format(mode)) + ### subvolume operations - def create_subvolume(self, volname, subvolname, groupname, size, pool=None): + def create_subvolume(self, volname, subvolname, groupname, size, mode='755', pool=None): ret = 0, "", "" try: if not self.volume_exists(volname): @@ -184,7 +191,7 @@ class VolumeClient(object): raise VolumeException( -errno.ENOENT, "Subvolume group '{0}' not found, create it with " \ "`ceph fs subvolumegroup create` before creating subvolumes".format(groupname)) - sv.create_subvolume(spec, size, pool=pool) + sv.create_subvolume(spec, size, pool=pool, mode=self.octal_str_to_decimal_int(mode)) except VolumeException as ve: ret = self.volume_exception_to_retval(ve) return ret @@ -284,7 +291,7 @@ class VolumeClient(object): ### group operations - def create_subvolume_group(self, volname, groupname, pool=None): + def create_subvolume_group(self, volname, groupname, mode='755', pool=None): ret = 0, "", "" try: if not self.volume_exists(volname): @@ -295,7 +302,7 @@ class VolumeClient(object): # TODO: validate that subvol size fits in volume size with SubVolume(self.mgr, fs_name=volname) as sv: spec = SubvolumeSpec("", groupname) - sv.create_group(spec, pool=pool) + sv.create_group(spec, pool=pool, mode=self.octal_str_to_decimal_int(mode)) except VolumeException as ve: ret = self.volume_exception_to_retval(ve) return ret diff --git a/src/pybind/mgr/volumes/module.py b/src/pybind/mgr/volumes/module.py index 98b18c67eba1..6548cc0c0c84 100644 --- a/src/pybind/mgr/volumes/module.py +++ b/src/pybind/mgr/volumes/module.py @@ -47,9 +47,10 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): 'cmd': 'fs subvolumegroup create ' 'name=vol_name,type=CephString ' 'name=group_name,type=CephString ' - 'name=pool_layout,type=CephString,req=false ', + 'name=pool_layout,type=CephString,req=false ' + 'name=mode,type=CephString,req=false ', 'desc': "Create a CephFS subvolume group in a volume, and optionally, " - "with a specific data pool layout", + "with a specific data pool layout, and a specific numeric mode", 'perm': 'rw' }, { @@ -66,10 +67,11 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): 'name=sub_name,type=CephString ' 'name=size,type=CephInt,req=false ' 'name=group_name,type=CephString,req=false ' - 'name=pool_layout,type=CephString,req=false ', + 'name=pool_layout,type=CephString,req=false ' + 'name=mode,type=CephString,req=false ', 'desc': "Create a CephFS subvolume in a volume, and optionally, " - "with a specific size (in bytes), a specific data pool layout " - "and in a specific subvolume group", + "with a specific size (in bytes), a specific data pool layout, " + "a specific mode, and in a specific subvolume group", 'perm': 'rw' }, { @@ -201,8 +203,9 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): vol_name = cmd['vol_name'] group_name = cmd['group_name'] pool_layout = cmd.get('pool_layout', None) + mode = cmd.get('mode', '755') - return self.vc.create_subvolume_group(vol_name, group_name, pool=pool_layout) + return self.vc.create_subvolume_group(vol_name, group_name, mode=mode, pool=pool_layout) def _cmd_fs_subvolumegroup_rm(self, inbuf, cmd): """ @@ -223,8 +226,9 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): size = cmd.get('size', None) group_name = cmd.get('group_name', None) pool_layout = cmd.get('pool_layout', None) + mode = cmd.get('mode', '755') - return self.vc.create_subvolume(vol_name, sub_name, group_name, size, pool=pool_layout) + return self.vc.create_subvolume(vol_name, sub_name, group_name, size, mode=mode, pool=pool_layout) def _cmd_fs_subvolume_rm(self, inbuf, cmd): """