From: Shweta Bhosale Date: Wed, 21 Jan 2026 15:43:39 +0000 (+0530) Subject: mgr/cephadm: Updated NFS default protocol to v4 and v3 is enabled only when enable_nf... X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=9b0becfdf248576565481369780f5599766c3810;p=ceph.git mgr/cephadm: Updated NFS default protocol to v4 and v3 is enabled only when enable_nfsv3 is set in the spec Fixes: https://tracker.ceph.com/issues/74492 Signed-off-by: Shweta Bhosale --- diff --git a/doc/cephadm/services/nfs.rst b/doc/cephadm/services/nfs.rst index 07d19df950d..ecb31bff93f 100644 --- a/doc/cephadm/services/nfs.rst +++ b/doc/cephadm/services/nfs.rst @@ -60,6 +60,7 @@ Alternatively, an NFS service can be applied using a YAML specification. host2: 10.0.0.124 monitoring_networks: - 192.168.124.0/24 + enable_nfsv3: true In this example, we run the server on the non-default ``port`` of @@ -78,6 +79,8 @@ IP address is assigned to the host, that IP address will be used. If the IP address is not present and ``monitoring_networks`` is specified, an IP address that matches one of the specified networks will be used. If neither condition is met, the default binding will happen on all available network interfaces. +By default, only the NFSv4 protocol is enabled. NFSv3 can be enabled by setting +``enable_nfsv3`` to ``true`` in the service specification. NFS over RDMA ------------- diff --git a/doc/mgr/nfs.rst b/doc/mgr/nfs.rst index e09378b26cd..4ef7a9581b9 100644 --- a/doc/mgr/nfs.rst +++ b/doc/mgr/nfs.rst @@ -31,7 +31,7 @@ Create NFS Ganesha Cluster .. prompt:: bash # - ceph nfs cluster create [] [--ingress] [--virtual_ip ] [--ingress-mode {default|keepalive-only|haproxy-standard|haproxy-protocol}] [--port ] [--enable-rdma] [--rdma_port ] [-i ] + ceph nfs cluster create [] [--ingress] [--virtual_ip ] [--ingress-mode {default|keepalive-only|haproxy-standard|haproxy-protocol}] [--port ] [--enable-rdma] [--rdma_port ] [-i ] [--enable-nfsv3] This creates a common recovery pool for all NFS Ganesha daemons, new user based on ``cluster_id``, and a common NFS Ganesha config RADOS object. @@ -62,6 +62,9 @@ cluster):: NFS can be deployed on a port other than 2049 (the default) with ``--port ``. +By default, only NFS v4 protocol is enabled. To enable both NFS v3 and v4 protocols, +add the ``--enable-nfsv3`` flag. + To deploy NFS with a high-availability front-end (virtual IP and load balancer), add the ``--ingress`` flag and specify a virtual IP address. This will deploy a combination of keepalived and haproxy to provide an high-availability NFS frontend for the NFS diff --git a/src/pybind/mgr/cephadm/services/nfs.py b/src/pybind/mgr/cephadm/services/nfs.py index ac01900eb02..1c26f8a0644 100644 --- a/src/pybind/mgr/cephadm/services/nfs.py +++ b/src/pybind/mgr/cephadm/services/nfs.py @@ -261,7 +261,8 @@ class NFSService(CephService): "tls_min_version": spec.tls_min_version, "tls_ktls": spec.tls_ktls, "tls_debug": spec.tls_debug, - "ceph_nodes": ceph_nodes + "ceph_nodes": ceph_nodes, + "protocols": "3, 4" if spec.enable_nfsv3 else "4" } if spec.enable_haproxy_protocol: context["haproxy_hosts"] = self._haproxy_hosts() diff --git a/src/pybind/mgr/cephadm/templates/services/nfs/ganesha.conf.j2 b/src/pybind/mgr/cephadm/templates/services/nfs/ganesha.conf.j2 index 606b1c5704f..2d211f4e7b0 100644 --- a/src/pybind/mgr/cephadm/templates/services/nfs/ganesha.conf.j2 +++ b/src/pybind/mgr/cephadm/templates/services/nfs/ganesha.conf.j2 @@ -3,9 +3,9 @@ NFS_CORE_PARAM { Enable_NLM = {{ enable_nlm }}; Enable_RQUOTA = false; {% if enable_rdma %} - Protocols = 3, 4, nfsrdma, rpcrdma; + Protocols = {{ protocols }}, nfsrdma, rpcrdma; {% else %} - Protocols = 3, 4; + Protocols = {{ protocols }}; {% endif %} mount_path_pseudo = true; Enable_UDP = false; diff --git a/src/pybind/mgr/cephadm/tests/services/test_ingress.py b/src/pybind/mgr/cephadm/tests/services/test_ingress.py index 86692935e18..a5bbe078d6e 100644 --- a/src/pybind/mgr/cephadm/tests/services/test_ingress.py +++ b/src/pybind/mgr/cephadm/tests/services/test_ingress.py @@ -1188,7 +1188,7 @@ class TestIngressService: 'NFS_CORE_PARAM {\n' ' Enable_NLM = true;\n' ' Enable_RQUOTA = false;\n' - ' Protocols = 3, 4;\n' + ' Protocols = 4;\n' ' mount_path_pseudo = true;\n' ' Enable_UDP = false;\n' ' NFS_Port = 2049;\n' diff --git a/src/pybind/mgr/cephadm/tests/services/test_nfs.py b/src/pybind/mgr/cephadm/tests/services/test_nfs.py index 376fdea25e3..115832e4635 100644 --- a/src/pybind/mgr/cephadm/tests/services/test_nfs.py +++ b/src/pybind/mgr/cephadm/tests/services/test_nfs.py @@ -588,6 +588,32 @@ class TestNFS: assert "nfsrdma" not in ganesha_conf assert "NFS_RDMA_Port" not in ganesha_conf + @patch("cephadm.serve.CephadmServe._run_cephadm") + @patch("cephadm.services.nfs.NFSService.fence_old_ranks", MagicMock()) + @patch("cephadm.services.nfs.NFSService.run_grace_tool", MagicMock()) + @patch("cephadm.services.nfs.NFSService.purge", MagicMock()) + @patch("cephadm.services.nfs.NFSService.create_rados_config_obj", MagicMock()) + def test_nfs_enable_nfsv3(self, _run_cephadm, cephadm_module: CephadmOrchestrator): + _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) + + with with_host(cephadm_module, 'test'): + # Test with enable_nfsv3=False (default) + nfs_spec = NFSServiceSpec(service_id="foo", placement=PlacementSpec(hosts=['test'])) + with with_service(cephadm_module, nfs_spec) as _: + nfs_generated_conf, _ = service_registry.get_service('nfs').generate_config( + CephadmDaemonDeploySpec(host='test', daemon_id='foo.test.0.0', service_name=nfs_spec.service_name())) + ganesha_conf = nfs_generated_conf['files']['ganesha.conf'] + assert "Protocols = 4;" in ganesha_conf + + # Test with enable_nfsv3=True + nfs_spec = NFSServiceSpec(service_id="foo", placement=PlacementSpec(hosts=['test']), + enable_nfsv3=True) + with with_service(cephadm_module, nfs_spec) as _: + nfs_generated_conf, _ = service_registry.get_service('nfs').generate_config( + CephadmDaemonDeploySpec(host='test', daemon_id='foo.test.0.0', service_name=nfs_spec.service_name())) + ganesha_conf = nfs_generated_conf['files']['ganesha.conf'] + assert "Protocols = 3, 4;" in ganesha_conf + def test_nfs_colocation_ports_validation(): """Test validation of colocation_ports in NFSServiceSpec""" diff --git a/src/pybind/mgr/nfs/cluster.py b/src/pybind/mgr/nfs/cluster.py index 5a4cf057aa2..1beff39ff93 100644 --- a/src/pybind/mgr/nfs/cluster.py +++ b/src/pybind/mgr/nfs/cluster.py @@ -161,6 +161,7 @@ class NFSCluster: ingress_mode: Optional[IngressType] = None, port: Optional[int] = None, cluster_qos_config: Optional[Dict[str, Union[str, bool, int]]] = None, + enable_nfsv3: bool = False, ssl: bool = False, ssl_cert: Optional[str] = None, ssl_key: Optional[str] = None, @@ -206,6 +207,7 @@ class NFSCluster: virtual_ip=virtual_ip_for_ganesha, enable_haproxy_protocol=enable_haproxy_protocol, cluster_qos_config=cluster_qos_config, + enable_nfsv3=enable_nfsv3, ssl=ssl, ssl_cert=ssl_cert, ssl_key=ssl_key, @@ -235,6 +237,7 @@ class NFSCluster: placement=PlacementSpec.from_string(placement), port=port, cluster_qos_config=cluster_qos_config, + enable_nfsv3=enable_nfsv3, ssl=ssl, ssl_cert=ssl_cert, ssl_key=ssl_key, @@ -269,6 +272,7 @@ class NFSCluster: ingress_mode: Optional[IngressType] = None, port: Optional[int] = None, cluster_qos_config: Optional[Dict[str, Union[str, bool, int]]] = None, + enable_nfsv3: bool = False, ssl: bool = False, ssl_cert: Optional[str] = None, ssl_key: Optional[str] = None, @@ -309,6 +313,7 @@ class NFSCluster: ingress_mode, port, cluster_qos_config=cluster_qos_config, + enable_nfsv3=enable_nfsv3, ssl=ssl, ssl_cert=ssl_cert, ssl_key=ssl_key, diff --git a/src/pybind/mgr/nfs/module.py b/src/pybind/mgr/nfs/module.py index ab6369e346e..7cd2aa70dcc 100644 --- a/src/pybind/mgr/nfs/module.py +++ b/src/pybind/mgr/nfs/module.py @@ -162,6 +162,7 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): port: Optional[int] = None, enable_rdma: bool = False, rdma_port: Optional[int] = None, + enable_nfsv3: bool = False, inbuf: Optional[str] = None) -> None: """Create an NFS Cluster""" cluster_qos_config = None @@ -183,6 +184,7 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): virtual_ip=virtual_ip, ingress=ingress, ingress_mode=ingress_mode, port=port, cluster_qos_config=cluster_qos_config, + enable_nfsv3=enable_nfsv3, ssl=ssl, ssl_cert=ssl_cert, ssl_key=ssl_key, diff --git a/src/python-common/ceph/deployment/service_spec.py b/src/python-common/ceph/deployment/service_spec.py index 9ac9db45871..c0b9ff873d5 100644 --- a/src/python-common/ceph/deployment/service_spec.py +++ b/src/python-common/ceph/deployment/service_spec.py @@ -1393,6 +1393,7 @@ class NFSServiceSpec(ServiceSpec): tls_min_version: Optional[str] = None, tls_ciphers: Optional[str] = None, colocation_ports: Optional[List[Dict[str, int]]] = None, + enable_nfsv3: bool = False, ): assert service_type == 'nfs' super(NFSServiceSpec, self).__init__( @@ -1421,6 +1422,7 @@ class NFSServiceSpec(ServiceSpec): self.rdma_port = rdma_port self.cluster_qos_config = cluster_qos_config self.cluster_qos_port = cluster_qos_port + self.enable_nfsv3 = enable_nfsv3 # colocation_ports is a list of port dicts for ADDITIONAL colocated daemons # The first daemon always uses port and monitoring_port from the spec