]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/volumes: uid, gid for subvolume create and subvolumegroup create commands
authorJos Collin <jcollin@redhat.com>
Wed, 11 Sep 2019 09:57:42 +0000 (15:27 +0530)
committerJos Collin <jcollin@redhat.com>
Tue, 5 Nov 2019 06:06:29 +0000 (11:36 +0530)
Allow setting uid, gid for subvolume create and subvolumegroup create commands

Fixes: https://tracker.ceph.com/issues/40959
Signed-off-by: Jos Collin <jcollin@redhat.com>
src/pybind/mgr/volumes/fs/subvolume.py
src/pybind/mgr/volumes/fs/volume.py
src/pybind/mgr/volumes/module.py

index defa2b46cd980907b6d364bdb56938bf6329d261..e79b0e0a7453f593df41c6ddcb29abc5a1991e61 100644 (file)
@@ -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
@@ -210,7 +231,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:
@@ -221,6 +252,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
index 0187cc1b890278609652f8c331e49a384df0ef42..a9e049529fae09f043c2e79de6f9c5b6d746c874 100644 (file)
@@ -387,6 +387,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:
@@ -396,7 +398,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
@@ -550,13 +552,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
index 367c024cb7c8105fb3350d2ff8ca3b35c4d2642c..567b20aac25c033ce6835b68c112836502eb98cd 100644 (file)
@@ -37,6 +37,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",
@@ -64,6 +66,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, "
@@ -200,7 +204,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):
         """
@@ -223,6 +228,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):