From 416425c5fde39a9b42c5d70bb6bda3bd576456c3 Mon Sep 17 00:00:00 2001 From: Teoman ONAY Date: Tue, 28 Mar 2023 14:18:14 +0200 Subject: [PATCH] mgr/cephadm: add idmap.conf customization for NFS server Allows idmapd.conf to be customized to control the NFSv4.x server configuration Fixes: https://tracker.ceph.com/issues/64577 Signed-off-by: Teoman ONAY --- src/cephadm/cephadmlib/daemons/nfs.py | 2 +- src/cephadm/tests/test_deploy.py | 1 + src/cephadm/tests/test_nfs.py | 1 + src/pybind/mgr/cephadm/services/nfs.py | 20 +++++++++++++++++++ .../templates/services/nfs/ganesha.conf.j2 | 3 +++ src/pybind/mgr/cephadm/tests/test_services.py | 3 ++- .../ceph/deployment/service_spec.py | 2 ++ .../ceph/tests/test_service_spec.py | 6 ++++++ 8 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/cephadm/cephadmlib/daemons/nfs.py b/src/cephadm/cephadmlib/daemons/nfs.py index 6e2f2a945cae5..f09374d5f4648 100644 --- a/src/cephadm/cephadmlib/daemons/nfs.py +++ b/src/cephadm/cephadmlib/daemons/nfs.py @@ -31,7 +31,7 @@ class NFSGanesha(ContainerDaemonForm): entrypoint = '/usr/bin/ganesha.nfsd' daemon_args = ['-F', '-L', 'STDERR'] - required_files = ['ganesha.conf'] + required_files = ['ganesha.conf', 'idmap.conf'] port_map = { 'nfs': 2049, diff --git a/src/cephadm/tests/test_deploy.py b/src/cephadm/tests/test_deploy.py index cfde3fbce0aab..fc2bbe4b3e3d8 100644 --- a/src/cephadm/tests/test_deploy.py +++ b/src/cephadm/tests/test_deploy.py @@ -49,6 +49,7 @@ def test_deploy_nfs_container(cephadm_fs, funkypatch): 'pool': 'foo', 'files': { 'ganesha.conf': 'FAKE', + 'idmap.conf': 'FAKE', }, 'config': 'BALONEY', 'keyring': 'BUNKUS', diff --git a/src/cephadm/tests/test_nfs.py b/src/cephadm/tests/test_nfs.py index aae8113382dc3..1b468516e67b6 100644 --- a/src/cephadm/tests/test_nfs.py +++ b/src/cephadm/tests/test_nfs.py @@ -25,6 +25,7 @@ def nfs_json(**kwargs): if kwargs.get("files"): result["files"] = { "ganesha.conf": "", + "idmap.conf": "", } if kwargs.get("rgw_content"): result["rgw"] = dict(kwargs["rgw_content"]) diff --git a/src/pybind/mgr/cephadm/services/nfs.py b/src/pybind/mgr/cephadm/services/nfs.py index f94a00f5bdf94..e0c61b117e7eb 100644 --- a/src/pybind/mgr/cephadm/services/nfs.py +++ b/src/pybind/mgr/cephadm/services/nfs.py @@ -5,6 +5,8 @@ import subprocess import tempfile from typing import Dict, Tuple, Any, List, cast, Optional +from configparser import ConfigParser +from io import StringIO from mgr_module import HandleCommandResult from mgr_module import NFS_POOL_NAME as POOL_NAME @@ -79,6 +81,8 @@ def generate_config(self, daemon_spec: CephadmDaemonDeploySpec) -> Tuple[Dict[st nodeid = f'{daemon_spec.service_name}.{daemon_spec.rank}' + nfs_idmap_conf = '/etc/ganesha/idmap.conf' + # create the RADOS recovery pool keyring rados_user = f'{daemon_type}.{daemon_id}' rados_keyring = self.create_keyring(daemon_spec) @@ -115,12 +119,27 @@ def get_ganesha_conf() -> str: "port": daemon_spec.ports[0] if daemon_spec.ports else 2049, "bind_addr": bind_addr, "haproxy_hosts": [], + "nfs_idmap_conf": nfs_idmap_conf, } if spec.enable_haproxy_protocol: context["haproxy_hosts"] = self._haproxy_hosts() logger.debug("selected haproxy_hosts: %r", context["haproxy_hosts"]) return self.mgr.template.render('services/nfs/ganesha.conf.j2', context) + # generate the idmap config + def get_idmap_conf() -> str: + idmap_conf = spec.idmap_conf + output = '' + if idmap_conf is not None: + cp = ConfigParser() + out = StringIO() + cp.read_dict(idmap_conf) + cp.write(out) + out.seek(0) + output = out.read() + out.close() + return output + # generate the cephadm config json def get_cephadm_config() -> Dict[str, Any]: config: Dict[str, Any] = {} @@ -130,6 +149,7 @@ def get_cephadm_config() -> Dict[str, Any]: config['extra_args'] = ['-N', 'NIV_EVENT'] config['files'] = { 'ganesha.conf': get_ganesha_conf(), + 'idmap.conf': get_idmap_conf() } config.update( self.get_config_and_keyring( 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 ab8df71923b49..7bc0278d7ed12 100644 --- a/src/pybind/mgr/cephadm/templates/services/nfs/ganesha.conf.j2 +++ b/src/pybind/mgr/cephadm/templates/services/nfs/ganesha.conf.j2 @@ -16,6 +16,9 @@ NFSv4 { Delegations = false; RecoveryBackend = 'rados_cluster'; Minor_Versions = 1, 2; +{% if nfs_idmap_conf %} + IdmapConf = "{{ nfs_idmap_conf }}"; +{% endif %} } RADOS_KV { diff --git a/src/pybind/mgr/cephadm/tests/test_services.py b/src/pybind/mgr/cephadm/tests/test_services.py index dbab022058d42..93c426f61a923 100644 --- a/src/pybind/mgr/cephadm/tests/test_services.py +++ b/src/pybind/mgr/cephadm/tests/test_services.py @@ -2448,6 +2448,7 @@ def fake_keys(): ' Delegations = false;\n' " RecoveryBackend = 'rados_cluster';\n" ' Minor_Versions = 1, 2;\n' + ' IdmapConf = "/etc/ganesha/idmap.conf";\n' '}\n' '\n' 'RADOS_KV {\n' @@ -2471,7 +2472,7 @@ def fake_keys(): "%url rados://.nfs/foo/conf-nfs.foo" ) nfs_expected_conf = { - 'files': {'ganesha.conf': nfs_ganesha_txt}, + 'files': {'ganesha.conf': nfs_ganesha_txt, 'idmap.conf': ''}, 'config': '', 'extra_args': ['-N', 'NIV_EVENT'], 'keyring': ( diff --git a/src/python-common/ceph/deployment/service_spec.py b/src/python-common/ceph/deployment/service_spec.py index f6d290f071888..23ac1486715f4 100644 --- a/src/python-common/ceph/deployment/service_spec.py +++ b/src/python-common/ceph/deployment/service_spec.py @@ -1093,6 +1093,7 @@ def __init__(self, enable_haproxy_protocol: bool = False, extra_container_args: Optional[GeneralArgList] = None, extra_entrypoint_args: Optional[GeneralArgList] = None, + idmap_conf: Optional[Dict[str, Dict[str, str]]] = None, custom_configs: Optional[List[CustomConfig]] = None, ): assert service_type == 'nfs' @@ -1105,6 +1106,7 @@ def __init__(self, self.port = port self.virtual_ip = virtual_ip self.enable_haproxy_protocol = enable_haproxy_protocol + self.idmap_conf = idmap_conf def get_port_start(self) -> List[int]: if self.port: diff --git a/src/python-common/ceph/tests/test_service_spec.py b/src/python-common/ceph/tests/test_service_spec.py index 9a55b0a813598..538ee97edfae4 100644 --- a/src/python-common/ceph/tests/test_service_spec.py +++ b/src/python-common/ceph/tests/test_service_spec.py @@ -396,6 +396,12 @@ def test_osd_unmanaged(): service_id: mynfs service_name: nfs.mynfs spec: + idmap_conf: + general: + local-realms: domain.org + mapping: + nobody-group: nfsnobody + nobody-user: nfsnobody port: 1234 --- service_type: iscsi