From da7ecec05680a090c820f21233594a7cda8e0e70 Mon Sep 17 00:00:00 2001 From: Rongqi Sun Date: Tue, 7 Mar 2023 17:12:31 +0800 Subject: [PATCH] cephadm: eliminate duplication of sections Signed-off-by: Rongqi Sun (cherry picked from commit 0d1596e9275e8ca1b8c09b1490b3e595130aa97b) --- src/pybind/mgr/cephadm/module.py | 33 +++++++++++++- src/pybind/mgr/cephadm/tests/test_cephadm.py | 46 ++++++++++++++++++-- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/src/pybind/mgr/cephadm/module.py b/src/pybind/mgr/cephadm/module.py index 8e468e3c8d4af..698fc46596f8f 100644 --- a/src/pybind/mgr/cephadm/module.py +++ b/src/pybind/mgr/cephadm/module.py @@ -1827,9 +1827,40 @@ Then run the following: }) extra = self.extra_ceph_conf().conf if extra: - config += extra.strip().replace('[global]','') + '\n' + try: + config = self._combine_confs(config, extra) + except Exception as e: + self.log.error(f'Failed to add extra ceph conf settings to minimal ceph conf: {e}') return config + def _combine_confs(self, conf1: str, conf2: str) -> str: + section_to_option: Dict[str, List[str]] = {} + final_conf: str = '' + for conf in [conf1, conf2]: + if not conf: + continue + section = '' + for line in conf.split('\n'): + if line.strip().startswith('#') or not line.strip(): + continue + if line.strip().startswith('[') and line.strip().endswith(']'): + section = line.strip().replace('[', '').replace(']', '') + if section not in section_to_option: + section_to_option[section] = [] + else: + section_to_option[section].append(line.strip()) + + first_section = True + for section, options in section_to_option.items(): + if not first_section: + final_conf += '\n' + final_conf += f'[{section}]\n' + for option in options: + final_conf += f'{option}\n' + first_section = False + + return final_conf + def _invalidate_daemons_and_kick_serve(self, filter_host: Optional[str] = None) -> None: if filter_host: self.cache.invalidate_host_daemons(filter_host) diff --git a/src/pybind/mgr/cephadm/tests/test_cephadm.py b/src/pybind/mgr/cephadm/tests/test_cephadm.py index 1d17b267e3f35..fc5a6996e0e15 100644 --- a/src/pybind/mgr/cephadm/tests/test_cephadm.py +++ b/src/pybind/mgr/cephadm/tests/test_cephadm.py @@ -458,7 +458,7 @@ class TestCephadm(object): '--config-json', '-', '--reconfig', ], - stdin='{"config": "\\n\\n[mon]\\nk=v\\n[mon.test]\\npublic network = 127.0.0.0/8\\n", ' + stdin='{"config": "[mon]\\nk=v\\n[mon.test]\\npublic network = 127.0.0.0/8\\n", ' + '"keyring": "", "files": {"config": "[mon.test]\\npublic network = 127.0.0.0/8\\n"}}', image='') @@ -1870,10 +1870,10 @@ class TestCephadm(object): CephadmServe(cephadm_module)._write_all_client_files() _write_file.assert_has_calls([mock.call('test', '/etc/ceph/ceph.conf', - b'\n\n[mon]\nk=v\n', 0o644, 0, 0, None), + b'[mon]\nk=v\n', 0o644, 0, 0, None), mock.call('test', '/var/lib/ceph/fsid/config/ceph.conf', - b'\n\n[mon]\nk=v\n', 0o644, 0, 0, None)]) + b'[mon]\nk=v\n', 0o644, 0, 0, None)]) # reload cephadm_module.cache.last_client_files = {} cephadm_module.cache.load() @@ -1901,6 +1901,46 @@ class TestCephadm(object): with with_cephadm_module({'manage_etc_ceph_ceph_conf': True}) as m: assert m.manage_etc_ceph_ceph_conf is True + @mock.patch("cephadm.CephadmOrchestrator.check_mon_command") + @mock.patch("cephadm.CephadmOrchestrator.extra_ceph_conf") + def test_extra_ceph_conf(self, _extra_ceph_conf, _check_mon_cmd, cephadm_module: CephadmOrchestrator): + # settings put into the [global] section in the extra conf + # need to be appended to existing [global] section in given + # minimal ceph conf, but anything in another section (e.g. [mon]) + # needs to continue to be its own section + + # this is the conf "ceph generate-minimal-conf" will return in this test + _check_mon_cmd.return_value = (0, """[global] +global_k1 = global_v1 +global_k2 = global_v2 +[mon] +mon_k1 = mon_v1 +[osd] +osd_k1 = osd_v1 +osd_k2 = osd_v2 +""", '') + + # test with extra ceph conf that has some of the sections from minimal conf + _extra_ceph_conf.return_value = CephadmOrchestrator.ExtraCephConf(conf="""[mon] +mon_k2 = mon_v2 +[global] +global_k3 = global_v3 +""", last_modified=datetime_now()) + + expected_combined_conf = """[global] +global_k1 = global_v1 +global_k2 = global_v2 +global_k3 = global_v3 +[mon] +mon_k1 = mon_v1 +mon_k2 = mon_v2 +[osd] +osd_k1 = osd_v1 +osd_k2 = osd_v2 +""" + + assert cephadm_module.get_minimal_ceph_conf() == expected_combined_conf + @mock.patch("cephadm.serve.CephadmServe._run_cephadm") def test_registry_login(self, _run_cephadm, cephadm_module: CephadmOrchestrator): def check_registry_credentials(url, username, password): -- 2.39.5