]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
pybind/mgr: add option to set unicode normalization to a subvolume
authorXavi Hernandez <xhernandez@gmail.com>
Wed, 19 Mar 2025 12:05:19 +0000 (13:05 +0100)
committerPatrick Donnelly <pdonnell@ibm.com>
Tue, 23 Sep 2025 14:43:52 +0000 (10:43 -0400)
Add an option to explicitly set the unicode normalization form to use on
a CephFS subvolume.

Signed-off-by: Xavi Hernandez <xhernandez@gmail.com>
(cherry picked from commit b8b0f1f3d1b57eec557dc82dfa96a81e2b1e41bf)

src/pybind/mgr/volumes/fs/operations/subvolume.py
src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py
src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py
src/pybind/mgr/volumes/fs/volume.py
src/pybind/mgr/volumes/module.py

index 256c8d7607492d5e6021692f7f089273b79d0521..bac51a4289502bf0a2d6e95a560d356898c48379 100644 (file)
@@ -5,7 +5,7 @@ from .group import open_group
 from .template import SubvolumeOpType
 from .versions import loaded_subvolumes
 
-def create_subvol(mgr, fs, vol_spec, group, subvolname, size, isolate_nspace, pool, mode, uid, gid, earmark):
+def create_subvol(mgr, fs, vol_spec, group, subvolname, size, isolate_nspace, pool, mode, uid, gid, earmark, normalization):
     """
     create a subvolume (create a subvolume with the max known version).
 
@@ -19,10 +19,11 @@ def create_subvol(mgr, fs, vol_spec, group, subvolname, size, isolate_nspace, po
     :param uid: the user identifier
     :param gid: the group identifier
     :param earmark: metadata string to identify if subvolume is associated with nfs/smb
+    :param normalization: the unicode normalization form to use (nfd, nfc, nfkd or nfkc)
     :return: None
     """
     subvolume = loaded_subvolumes.get_subvolume_object_max(mgr, fs, vol_spec, group, subvolname)
-    subvolume.create(size, isolate_nspace, pool, mode, uid, gid, earmark)
+    subvolume.create(size, isolate_nspace, pool, mode, uid, gid, earmark, normalization)
 
 
 def create_clone(mgr, fs, vol_spec, group, subvolname, pool, source_volume, source_subvolume, snapname):
index acf4aa3e0d33e1b400947b137bc6af57339890b4..28cb7fb9d8e0bef86affe2ac6569909dd7270ddc 100644 (file)
@@ -85,7 +85,7 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate):
         """ Path to user data directory within a subvolume snapshot named 'snapname' """
         return self.snapshot_path(snapname)
 
-    def create(self, size, isolate_nspace, pool, mode, uid, gid, earmark):
+    def create(self, size, isolate_nspace, pool, mode, uid, gid, earmark, normalization):
         subvolume_type = SubvolumeTypes.TYPE_NORMAL
         try:
             initial_state = SubvolumeOpSm.get_init_state(subvolume_type)
@@ -104,7 +104,8 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate):
                 'data_pool': pool,
                 'pool_namespace': self.namespace if isolate_nspace else None,
                 'quota': size,
-                'earmark': earmark
+                'earmark': earmark,
+                'normalization': normalization,
             }
             self.set_attrs(subvol_path, attrs)
 
index bec271f659fbf58f8cd8bc003b115f7d64431c9d..2c4d493ec2cbfd7c694e84e09df85fb0c895cb41 100644 (file)
@@ -154,7 +154,7 @@ class SubvolumeV2(SubvolumeV1):
         self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_PATH, qpath)
         self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_STATE, initial_state.value)
 
-    def create(self, size, isolate_nspace, pool, mode, uid, gid, earmark):
+    def create(self, size, isolate_nspace, pool, mode, uid, gid, earmark, normalization):
         subvolume_type = SubvolumeTypes.TYPE_NORMAL
         try:
             initial_state = SubvolumeOpSm.get_init_state(subvolume_type)
@@ -176,7 +176,8 @@ class SubvolumeV2(SubvolumeV1):
                 'data_pool': pool,
                 'pool_namespace': self.namespace if isolate_nspace else None,
                 'quota': size,
-                'earmark': earmark
+                'earmark': earmark,
+                'normalization': normalization,
             }
             self.set_attrs(subvol_path, attrs)
 
index b9465552b93420f9f1f4524ce7e69022f03d2686..aed6825e0df55601003f5462d10123c9fd3f9feb 100644 (file)
@@ -226,12 +226,13 @@ class VolumeClient(CephfsClient["Module"]):
         mode       = kwargs['mode']
         isolate_nspace = kwargs['namespace_isolated']
         earmark    = kwargs['earmark'] or ''  # if not set, default to empty string --> no earmark
+        normalization = kwargs['normalization']
 
         oct_mode = octal_str_to_decimal_int(mode)
 
         try:
             create_subvol(
-                self.mgr, fs_handle, self.volspec, group, subvolname, size, isolate_nspace, pool, oct_mode, uid, gid, earmark)
+                self.mgr, fs_handle, self.volspec, group, subvolname, size, isolate_nspace, pool, oct_mode, uid, gid, earmark, normalization)
         except VolumeException as ve:
             # kick the purge threads for async removal -- note that this
             # assumes that the subvolume is moved to trashcan for cleanup on error.
@@ -250,6 +251,7 @@ class VolumeClient(CephfsClient["Module"]):
         mode       = kwargs['mode']
         isolate_nspace = kwargs['namespace_isolated']
         earmark    = kwargs['earmark'] or ''  # if not set, default to empty string --> no earmark
+        normalization = kwargs['normalization']
 
         try:
             with open_volume(self, volname) as fs_handle:
@@ -264,7 +266,8 @@ class VolumeClient(CephfsClient["Module"]):
                                 'data_pool': pool,
                                 'pool_namespace': subvolume.namespace if isolate_nspace else None,
                                 'quota': size,
-                                'earmark': earmark
+                                'earmark': earmark,
+                                'normalization': normalization,
                             }
                             subvolume.set_attrs(subvolume.path, attrs)
                     except VolumeException as ve:
index e8694709c530668463865052ddf66ce1241d074c..fcab5a70bc7899310e8f129234338641c75e593b 100644 (file)
@@ -142,7 +142,8 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
                    'name=gid,type=CephInt,req=false '
                    'name=mode,type=CephString,req=false '
                    'name=namespace_isolated,type=CephBool,req=false '
-                   'name=earmark,type=CephString,req=false ',
+                   'name=earmark,type=CephString,req=false '
+                   'name=normalization,type=CephChoices,strings=nfd|nfc|nfkd|nfkc,req=false ',
             'desc': "Create a CephFS subvolume in a volume, and optionally, "
                     "with a specific size (in bytes), a specific data pool layout, "
                     "a specific mode, in a specific subvolume group and in separate "
@@ -732,7 +733,8 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
                                         gid=cmd.get('gid', None),
                                         mode=cmd.get('mode', '755'),
                                         namespace_isolated=cmd.get('namespace_isolated', False),
-                                        earmark=cmd.get('earmark', None))
+                                        earmark=cmd.get('earmark', None),
+                                        normalization=cmd.get('normalization', None))
 
     @mgr_cmd_wrap
     def _cmd_fs_subvolume_rm(self, inbuf, cmd):