From 917fb597673ade3b436854d17aef559447540a85 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 26 Apr 2021 14:54:38 -0400 Subject: [PATCH] mgr/cephadm: nfs: shell out to rados tool for conf creation This avoids any hangs due to rados. Signed-off-by: Sage Weil --- src/pybind/mgr/cephadm/services/nfs.py | 45 +++++++++++--------- src/pybind/mgr/cephadm/tests/test_cephadm.py | 3 +- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/pybind/mgr/cephadm/services/nfs.py b/src/pybind/mgr/cephadm/services/nfs.py index 91fa3d5e5e9bb..72be22bafde96 100644 --- a/src/pybind/mgr/cephadm/services/nfs.py +++ b/src/pybind/mgr/cephadm/services/nfs.py @@ -8,7 +8,6 @@ from typing import Dict, Tuple, Any, List, cast, Optional from mgr_module import HandleCommandResult from ceph.deployment.service_spec import ServiceSpec, NFSServiceSpec -import rados from orchestrator import DaemonDescription @@ -138,24 +137,32 @@ class NFSService(CephService): def create_rados_config_obj(self, spec: NFSServiceSpec, clobber: bool = False) -> None: - with self.mgr.rados.open_ioctx(spec.pool) as ioctx: - if spec.namespace: - ioctx.set_namespace(spec.namespace) - - obj = spec.rados_config_name() - exists = True - try: - ioctx.stat(obj) - except rados.ObjectNotFound: - exists = False - - if exists and not clobber: - # Assume an existing config - logger.info('Rados config object exists: %s' % obj) - else: - # Create an empty config object - logger.info('Creating rados config object: %s' % obj) - ioctx.write_full(obj, ''.encode('utf-8')) + objname = spec.rados_config_name() + cmd = [ + 'rados', + '-n', f"mgr.{self.mgr.get_mgr_id()}", + '-k', str(self.mgr.get_ceph_option('keyring')), + '-p', cast(str, spec.pool), + ] + if spec.namespace: + cmd += ['--namespace', spec.namespace] + result = subprocess.run( + cmd + ['get', objname, '-'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + timeout=10) + if not result.returncode and not clobber: + logger.info('Rados config object exists: %s' % objname) + else: + logger.info('Creating rados config object: %s' % objname) + result = subprocess.run( + cmd + ['put', objname, '-'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + timeout=10) + if result.returncode: + self.mgr.log.warning( + f'Unable to create rados config object {objname}: {result.stderr.decode("utf-8")}' + ) + raise RuntimeError(result.stderr.decode("utf-8")) def create_keyring(self, daemon_spec: CephadmDaemonDeploySpec) -> str: daemon_id = daemon_spec.daemon_id diff --git a/src/pybind/mgr/cephadm/tests/test_cephadm.py b/src/pybind/mgr/cephadm/tests/test_cephadm.py index 167fcc664b941..18912fa4cc3e9 100644 --- a/src/pybind/mgr/cephadm/tests/test_cephadm.py +++ b/src/pybind/mgr/cephadm/tests/test_cephadm.py @@ -755,7 +755,7 @@ class TestCephadm(object): @mock.patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}')) @mock.patch("cephadm.services.nfs.NFSService.run_grace_tool", mock.MagicMock()) - @mock.patch("cephadm.module.CephadmOrchestrator.rados", mock.MagicMock()) + @mock.patch("cephadm.services.nfs.NFSService.create_rados_config_obj", mock.MagicMock()) def test_nfs(self, cephadm_module): with with_host(cephadm_module, 'test'): ps = PlacementSpec(hosts=['test'], count=1) @@ -917,6 +917,7 @@ class TestCephadm(object): @mock.patch("subprocess.run", None) @mock.patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}')) @mock.patch("cephadm.services.nfs.NFSService.run_grace_tool", mock.MagicMock()) + @mock.patch("cephadm.services.nfs.NFSService.create_rados_config_obj", mock.MagicMock()) def test_apply_save(self, spec: ServiceSpec, meth, cephadm_module: CephadmOrchestrator): with with_host(cephadm_module, 'test'): with with_service(cephadm_module, spec, meth, 'test'): -- 2.39.5