]> git.apps.os.sepia.ceph.com Git - ceph.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)
committerXavi Hernandez <xhernandez@gmail.com>
Tue, 25 Mar 2025 13:45:54 +0000 (14:45 +0100)
Add an option to explicitly set the unicode normalization form to use on
a CephFS subvolume.

Signed-off-by: Xavi Hernandez <xhernandez@gmail.com>
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 3440ab108c8574ee9ba269720567dd98e65bf4aa..019c2b878a9c687952005c7e70a9d7a1bf825d9e 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 b2e5d762af1814ff1e5e18a97fd53980fdcd15f2..0d09333463e2e71caf059644f7f5a015be508e23 100644 (file)
@@ -232,12 +232,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.
@@ -256,6 +257,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:
@@ -270,7 +272,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 622aef8362e33d34232cfe033ec7e79e960a8a1d..9281a925b6e999a7ab5c0d189292788175a0dff1 100644 (file)
@@ -144,7 +144,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 "
@@ -759,7 +760,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):