]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/volumes: Support subvolumegroup quota
authorKotresh HR <khiremat@redhat.com>
Fri, 18 Mar 2022 07:04:32 +0000 (12:34 +0530)
committerKotresh HR <khiremat@redhat.com>
Mon, 6 Jun 2022 07:10:46 +0000 (12:40 +0530)
Fixes: https://tracker.ceph.com/issues/53509
Signed-off-by: Kotresh HR <khiremat@redhat.com>
src/pybind/mgr/volumes/fs/operations/group.py
src/pybind/mgr/volumes/fs/volume.py
src/pybind/mgr/volumes/module.py

index 152383c51d43a3e1ae3ccf4b080d7b4b285deebf..1409c3e83676d50f2c6c2096163917da55e1fceb 100644 (file)
@@ -88,14 +88,65 @@ class Group(GroupTemplate):
                 return []
             raise
 
+def set_group_attrs(fs, path, attrs):
+    # set subvolume group attrs
+    # set size
+    quota = attrs.get("quota")
+    if quota is not None:
+        try:
+            fs.setxattr(path, 'ceph.quota.max_bytes', str(quota).encode('utf-8'), 0)
+        except cephfs.InvalidValue:
+            raise VolumeException(-errno.EINVAL, "invalid size specified: '{0}'".format(quota))
+        except cephfs.Error as e:
+            raise VolumeException(-e.args[0], e.args[1])
 
-def create_group(fs, vol_spec, groupname, pool, mode, uid, gid):
+    # set pool layout
+    pool = attrs.get("data_pool")
+    if not pool:
+        pool = get_ancestor_xattr(fs, path, "ceph.dir.layout.pool")
+    try:
+        fs.setxattr(path, 'ceph.dir.layout.pool', pool.encode('utf-8'), 0)
+    except cephfs.InvalidValue:
+        raise VolumeException(-errno.EINVAL,
+                              "Invalid pool layout '{0}'. It must be a valid data pool".format(pool))
+
+    # set uid/gid
+    uid = attrs.get("uid")
+    if uid is None:
+        uid = 0
+    else:
+        try:
+            uid = int(uid)
+            if uid < 0:
+                raise ValueError
+        except ValueError:
+            raise VolumeException(-errno.EINVAL, "invalid UID")
+
+    gid = attrs.get("gid")
+    if gid is None:
+        gid = 0
+    else:
+        try:
+            gid = int(gid)
+            if gid < 0:
+                raise ValueError
+        except ValueError:
+            raise VolumeException(-errno.EINVAL, "invalid GID")
+    fs.chown(path, uid, gid)
+
+    # set mode
+    mode = attrs.get("mode", None)
+    if mode is not None:
+        fs.lchmod(path, mode)
+
+def create_group(fs, vol_spec, groupname, size, pool, mode, uid, gid):
     """
     create a subvolume group.
 
     :param fs: ceph filesystem handle
     :param vol_spec: volume specification
     :param groupname: subvolume group name
+    :param size: In bytes, or None for no size limit
     :param pool: the RADOS pool where the data objects of the subvolumes will be stored
     :param mode: the user permissions
     :param uid: the user identifier
@@ -110,32 +161,13 @@ def create_group(fs, vol_spec, groupname, pool, mode, uid, gid):
     create_base_dir(fs, vol_spec_base_dir, vol_spec.DEFAULT_MODE)
     fs.mkdir(path, mode)
     try:
-        if not pool:
-            pool = get_ancestor_xattr(fs, path, "ceph.dir.layout.pool")
-        try:
-            fs.setxattr(path, 'ceph.dir.layout.pool', pool.encode('utf-8'), 0)
-        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
-        else:
-            try:
-                uid = int(uid)
-                if uid < 0:
-                    raise ValueError
-            except ValueError:
-                raise VolumeException(-errno.EINVAL, "invalid UID")
-        if gid is None:
-            gid = 0
-        else:
-            try:
-                gid = int(gid)
-                if gid < 0:
-                    raise ValueError
-            except ValueError:
-                raise VolumeException(-errno.EINVAL, "invalid GID")
-        fs.chown(path, uid, gid)
+        attrs = {
+            'uid': uid,
+            'gid': gid,
+            'data_pool': pool,
+            'quota': size
+        }
+        set_group_attrs(fs, path, attrs)
     except (cephfs.Error, VolumeException) as e:
         try:
             # cleanup group path on best effort basis
index 18c5da222fe15c8d3a0f472d4830fcf4b42739a3..7ba9c6bd9d51178b032ffba189f01fbe1c57f860 100644 (file)
@@ -11,7 +11,8 @@ from .fs_util import listdir
 
 from .operations.volume import create_volume, \
     delete_volume, rename_volume, list_volumes, open_volume, get_pool_names
-from .operations.group import open_group, create_group, remove_group, open_group_unique
+from .operations.group import open_group, create_group, remove_group, \
+    open_group_unique, set_group_attrs
 from .operations.subvolume import open_subvol, create_subvol, remove_subvol, \
     create_clone
 from .operations.trash import Trash
@@ -738,6 +739,7 @@ class VolumeClient(CephfsClient["Module"]):
         ret       = 0, "", ""
         volname    = kwargs['vol_name']
         groupname = kwargs['group_name']
+        size       = kwargs['size']
         pool      = kwargs['pool_layout']
         uid       = kwargs['uid']
         gid       = kwargs['gid']
@@ -746,13 +748,20 @@ class VolumeClient(CephfsClient["Module"]):
         try:
             with open_volume(self, volname) as fs_handle:
                 try:
-                    with open_group(fs_handle, self.volspec, groupname):
+                    with open_group(fs_handle, self.volspec, groupname) as group:
                         # idempotent creation -- valid.
-                        pass
+                        attrs = {
+                            'uid': uid,
+                            'gid': gid,
+                            'mode': octal_str_to_decimal_int(mode),
+                            'data_pool': pool,
+                            'quota': size
+                        }
+                        set_group_attrs(fs_handle, group.path, attrs)
                 except VolumeException as ve:
                     if ve.errno == -errno.ENOENT:
                         oct_mode = octal_str_to_decimal_int(mode)
-                        create_group(fs_handle, self.volspec, groupname, pool, oct_mode, uid, gid)
+                        create_group(fs_handle, self.volspec, groupname, size, pool, oct_mode, uid, gid)
                     else:
                         raise
         except VolumeException as ve:
index eb4a82f16565b1603bcfaedb5d303763d3b22883..aeec5ed3e60eb221bcba2aca0c9f7285cdb0aa12 100644 (file)
@@ -78,6 +78,7 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
             'cmd': 'fs subvolumegroup create '
                    'name=vol_name,type=CephString '
                    f'name=group_name,type=CephString,goodchars={goodchars} '
+                   'name=size,type=CephInt,req=false '
                    'name=pool_layout,type=CephString,req=false '
                    'name=uid,type=CephInt,req=false '
                    'name=gid,type=CephInt,req=false '
@@ -522,7 +523,7 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
         :return: a 3-tuple of return code(int), empty string(str), error message (str)
         """
         return self.vc.create_subvolume_group(
-            vol_name=cmd['vol_name'], group_name=cmd['group_name'],
+            vol_name=cmd['vol_name'], group_name=cmd['group_name'], size=cmd.get('size', None),
             pool_layout=cmd.get('pool_layout', None), mode=cmd.get('mode', '755'),
             uid=cmd.get('uid', None), gid=cmd.get('gid', None))