From ee853e26b0d484d0673212cb9aae6a8e89fdc193 Mon Sep 17 00:00:00 2001 From: Jos Collin Date: Wed, 11 Sep 2019 15:27:42 +0530 Subject: [PATCH] mgr/volumes: uid, gid for subvolume create and subvolumegroup create commands Allow setting uid, gid for subvolume create and subvolumegroup create commands Fixes: https://tracker.ceph.com/issues/40959 Signed-off-by: Jos Collin (cherry picked from commit 63226a73c491c4fee7879113b381489bed169d44) --- src/pybind/mgr/volumes/fs/subvolume.py | 53 ++++++++++++++++++++++++-- src/pybind/mgr/volumes/fs/volume.py | 8 +++- src/pybind/mgr/volumes/module.py | 9 ++++- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/pybind/mgr/volumes/fs/subvolume.py b/src/pybind/mgr/volumes/fs/subvolume.py index 8f3c2b1ab5ef4..9705a2473ae57 100644 --- a/src/pybind/mgr/volumes/fs/subvolume.py +++ b/src/pybind/mgr/volumes/fs/subvolume.py @@ -57,7 +57,8 @@ class SubVolume(object): ### basic subvolume operations - def create_subvolume(self, spec, size=None, namespace_isolated=True, mode=0o755, pool=None): + def create_subvolume(self, spec, size=None, pool=None, namespace_isolated=True, + uid=None, gid=None, mode=0o755): """ Set up metadata, pools and auth for a subvolume. @@ -66,8 +67,11 @@ class SubVolume(object): :param spec: subvolume path specification :param size: In bytes, or None for no size limit - :param namespace_isolated: If true, use separate RADOS namespace for this subvolume :param pool: the RADOS pool where the data objects of the subvolumes will be stored + :param namespace_isolated: If true, use separate RADOS namespace for this subvolume + :param uid: the user identifier + :param gid: the group identifier + :mode: the user permissions :return: None """ subvolpath = spec.subvolume_path @@ -101,6 +105,23 @@ class SubVolume(object): xattr_val = self._get_ancestor_xattr(subvolpath, "ceph.dir.layout.pool") # TODO: handle error... self.fs.setxattr(subvolpath, xattr_key, xattr_val.encode('utf-8'), 0) + + groupstat = self.fs.stat(spec.group_path) + if uid is None: + uid = int(groupstat.st_uid) + elif uid < 0: + raise VolumeException(-errno.EINVAL, "Provide a valid uid") + + if gid is None: + gid = int(groupstat.st_gid) + elif gid < 0: + raise VolumeException(-errno.EINVAL, "Provide a valid gid") + + try: + self.fs.chown(subvolpath, uid, gid) + except cephfs.InvalidValue: + raise VolumeException(-e.args[0], e.args[1]) + except Exception as e: try: # cleanup subvol path on best effort basis @@ -212,7 +233,17 @@ class SubVolume(object): ### group operations - def create_group(self, spec, mode=0o755, pool=None): + def create_group(self, spec, pool=None, uid=None, gid=None, mode=0o755): + """ + Create a subvolume group. + + :param spec: subvolume path specification + :param pool: the RADOS pool where the data objects of the subvolumes will be stored + :param uid: the user identifier + :param gid: the group identifier + :mode: the user permissions + :return: None + """ path = spec.group_path self.fs.mkdirs(path, mode) try: @@ -223,6 +254,22 @@ class SubVolume(object): except cephfs.InvalidValue: raise VolumeException(-errno.EINVAL, "Invalid pool layout '{0}'. It must be a valid data pool".format(pool)) + + if uid is None: + uid = 0 + elif uid < 0: + raise VolumeException(-errno.EINVAL, "Provide a valid uid") + + if gid is None: + gid = 0 + elif gid < 0: + raise VolumeException(-errno.EINVAL, "Provide a valid gid") + + try: + self.fs.chown(path, uid, gid) + except cephfs.InvalidValue: + raise VolumeException(-e.args[0], e.args[1]) + except Exception as e: try: # cleanup group path on best effort basis diff --git a/src/pybind/mgr/volumes/fs/volume.py b/src/pybind/mgr/volumes/fs/volume.py index 83ba46ff4a29f..ef3e4c789faf7 100644 --- a/src/pybind/mgr/volumes/fs/volume.py +++ b/src/pybind/mgr/volumes/fs/volume.py @@ -388,6 +388,8 @@ class VolumeClient(object): groupname = kwargs['group_name'] size = kwargs['size'] pool = kwargs['pool_layout'] + uid = kwargs['uid'] + gid = kwargs['gid'] mode = kwargs['mode'] try: @@ -397,7 +399,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, mode=self.octal_str_to_decimal_int(mode)) + sv.create_subvolume(spec, size, pool=pool, uid=uid, gid=gid, mode=self.octal_str_to_decimal_int(mode)) except VolumeException as ve: ret = self.volume_exception_to_retval(ve) return ret @@ -551,13 +553,15 @@ class VolumeClient(object): volname = kwargs['vol_name'] groupname = kwargs['group_name'] pool = kwargs['pool_layout'] + uid = kwargs['uid'] + gid = kwargs['gid'] mode = kwargs['mode'] try: # TODO: validate that subvol size fits in volume size with SubVolume(self.mgr, fs_handle) as sv: spec = SubvolumeSpec("", groupname) - sv.create_group(spec, pool=pool, mode=self.octal_str_to_decimal_int(mode)) + sv.create_group(spec, pool=pool, uid=uid, gid=gid, 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 0e710cfd5fc46..aaf8691150e69 100644 --- a/src/pybind/mgr/volumes/module.py +++ b/src/pybind/mgr/volumes/module.py @@ -53,6 +53,8 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): 'name=vol_name,type=CephString ' 'name=group_name,type=CephString ' 'name=pool_layout,type=CephString,req=false ' + 'name=uid,type=CephInt,req=false ' + 'name=gid,type=CephInt,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, and a specific numeric mode", @@ -80,6 +82,8 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): 'name=size,type=CephInt,req=false ' 'name=group_name,type=CephString,req=false ' 'name=pool_layout,type=CephString,req=false ' + 'name=uid,type=CephInt,req=false ' + 'name=gid,type=CephInt,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, " @@ -235,7 +239,8 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): """ return self.vc.create_subvolume_group( None, vol_name=cmd['vol_name'], group_name=cmd['group_name'], - pool_layout=cmd.get('pool_layout', None), mode=cmd.get('mode', '755')) + pool_layout=cmd.get('pool_layout', None), uid=cmd.get('uid', None), + gid=cmd.get('gid', None), mode=cmd.get('mode', '755')) def _cmd_fs_subvolumegroup_rm(self, inbuf, cmd): """ @@ -258,6 +263,8 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): group_name=cmd.get('group_name', None), size=cmd.get('size', None), pool_layout=cmd.get('pool_layout', None), + uid=cmd.get('uid', None), + gid=cmd.get('gid', None), mode=cmd.get('mode', '755')) def _cmd_fs_subvolume_rm(self, inbuf, cmd): -- 2.39.5