]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/nfs: set nfs export protocols based on cluster's protocol settings
authorShweta Bhosale <Shweta.Bhosale1@ibm.com>
Fri, 6 Feb 2026 12:57:58 +0000 (18:27 +0530)
committerShweta Bhosale <Shweta.Bhosale1@ibm.com>
Thu, 30 Apr 2026 13:41:17 +0000 (19:11 +0530)
Fixes: https://tracker.ceph.com/issues/74492
Signed-off-by: Shweta Bhosale <Shweta.Bhosale1@ibm.com>
src/pybind/mgr/nfs/export.py
src/pybind/mgr/nfs/ganesha_conf.py
src/pybind/mgr/nfs/tests/test_nfs.py

index 9194f380eb83c6baa628ba671cd8ccc686e78fbe..304d7c3511ef80789811012d31791adf77ed7b38 100644 (file)
@@ -162,6 +162,25 @@ class ExportMgr:
         self._exports: Optional[Dict[str, List[Export]]] = export_ls
         self.skip_notify_nfs_server = False
 
+    def _get_cluster_protocols(self, cluster_id: str) -> List[int]:
+        """Get the list of supported NFS protocols for a cluster.
+        """
+        try:
+            import orchestrator
+            from ceph.deployment.service_spec import NFSServiceSpec
+
+            completion = self.mgr.describe_service(service_type='nfs', service_name=f'nfs.{cluster_id}')
+            services = orchestrator.raise_if_exception(completion)
+            for service in services:
+                if service.spec and isinstance(service.spec, NFSServiceSpec):
+                    spec = cast(NFSServiceSpec, service.spec)
+                    if getattr(spec, 'enable_nfsv3', False):
+                        return [3, 4]
+                    return [4]
+        except Exception as e:
+            log.debug(f"Failed to get cluster protocols for {cluster_id}: {e}, defaulting to v4 only")
+        return [4]
+
     @property
     def exports(self) -> Dict[str, List[Export]]:
         if self._exports is None:
@@ -696,6 +715,8 @@ class ExportMgr:
             _validate_cmount_path(cmount_path, path)  # type: ignore
 
         pseudo_path = normalize_path(pseudo_path)
+        # Get the protocols based on cluster's enable_nfsv3 setting
+        protocols = self._get_cluster_protocols(cluster_id)
 
         export_dict = {
             "pseudo": pseudo_path,
@@ -710,6 +731,7 @@ class ExportMgr:
             "clients": clients,
             "sectype": sectype,
             "XprtSec": xprtsec,
+            "protocols": protocols,
         }
         if transports is not None:
             export_dict["transports"] = transports
@@ -750,6 +772,9 @@ class ExportMgr:
         if not bucket and not user_id:
             raise ErrorResponse("Must specify either bucket or user_id")
 
+        # Get the protocols based on cluster's enable_nfsv3 setting
+        protocols = self._get_cluster_protocols(cluster_id)
+
         export_dict = {
             "pseudo": pseudo_path,
             "path": bucket or '/',
@@ -762,6 +787,7 @@ class ExportMgr:
             "clients": clients,
             "sectype": sectype,
             "XprtSec": xprtsec,
+            "protocols": protocols,
         }
         if transports is not None:
             export_dict["transports"] = transports
@@ -825,6 +851,10 @@ class ExportMgr:
                 else:
                     new_export_dict['fsal']['cmount_path'] = '/'
 
+        # Set protocols based on cluster's enable_nfsv3 setting if not explicitly specified
+        if 'protocols' not in new_export_dict:
+            new_export_dict['protocols'] = self._get_cluster_protocols(cluster_id)
+
         new_export = self.create_export_from_dict(
             cluster_id,
             new_export_dict.get('export_id', self._gen_export_id(cluster_id)),
index 04f97bcba5522cccef52097447212186f70ccbf4..9a5b38fb92aace774df127b05c4d154ae53fdfdd 100644 (file)
@@ -474,7 +474,7 @@ class Export:
                    ex_dict.get('access_type', 'RO'),
                    ex_dict.get('squash', 'no_root_squash'),
                    ex_dict.get('security_label', True),
-                   ex_dict.get('protocols', [3, 4]),
+                   ex_dict.get('protocols', [4]),
                    ex_dict.get('transports', ['TCP']),
                    FSAL.from_dict(ex_dict.get('fsal', {})),
                    [Client.from_dict(client) for client in ex_dict.get('clients', [])],
index 57db70a2002e1621ea87d1da283066f86ce43cf8..3959f44f28a01b6af15b664c3c460320d588a8bd 100644 (file)
@@ -126,7 +126,7 @@ EXPORT {
     Path = /;
     Pseudo = /cephfs_b/;
     Access_Type = RW;
-    Protocols = 4;
+    Protocols = 3, 4;
     Attr_Expiration_Time = 0;
 
     FSAL {
@@ -491,7 +491,7 @@ NFS_CORE_PARAM {
         assert export.pseudo == "/cephfs_b/"
         assert export.access_type == "RW"
         assert export.squash == "no_root_squash"
-        assert export.protocols == [4]
+        assert export.protocols == [3, 4]
         assert export.fsal.name == "CEPH"
         assert export.fsal.user_id == "nfs.foo.b.lgudhr"
         assert export.fsal.fs_name == "b"
@@ -1122,7 +1122,7 @@ NFS_CORE_PARAM {
         assert export.pseudo == "/mybucket"
         assert export.access_type == "none"
         assert export.squash == "none"
-        assert export.protocols == [3, 4]
+        assert export.protocols == [4]
         assert export.transports == ["TCP"]
         assert export.fsal.name == "RGW"
         assert export.fsal.user_id == "bucket_owner_user"
@@ -1166,7 +1166,7 @@ NFS_CORE_PARAM {
         assert export.pseudo == "/mybucket"
         assert export.access_type == "none"
         assert export.squash == "none"
-        assert export.protocols == [3, 4]
+        assert export.protocols == [4]
         assert export.transports == ["TCP"]
         assert export.fsal.name == "RGW"
         assert export.fsal.access_key_id == "the_access_key"
@@ -1208,7 +1208,7 @@ NFS_CORE_PARAM {
         assert export.pseudo == "/mybucket"
         assert export.access_type == "none"
         assert export.squash == "none"
-        assert export.protocols == [3, 4]
+        assert export.protocols == [4]
         assert export.transports == ["TCP"]
         assert export.fsal.name == "RGW"
         assert export.fsal.access_key_id == "the_access_key"
@@ -1257,7 +1257,7 @@ NFS_CORE_PARAM {
         assert export.pseudo == "/cephfs2"
         assert export.access_type == "none"
         assert export.squash == "none"
-        assert export.protocols == [3, 4]
+        assert export.protocols == [4]
         assert export.transports == ["TCP"]
         assert export.fsal.name == "CEPH"
         assert export.fsal.user_id == "nfs.foo.myfs.86ca58ef"
@@ -1389,7 +1389,7 @@ EXPORT {
         assert export.pseudo == "/cephfs3"
         assert export.access_type == "RW"
         assert export.squash == "root"
-        assert export.protocols == [3, 4]
+        assert export.protocols == [4]
         assert export.fsal.name == "CEPH"
         assert export.fsal.user_id == "nfs.foo.myfs.86ca58ef"
         assert export.fsal.cephx_key == "thekeyforclientabc"