From: Rongqi Sun Date: Tue, 7 Mar 2023 09:12:31 +0000 (+0800) Subject: cephadm: eliminate duplication of sections X-Git-Tag: v18.1.0~130^2~27 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=9b7bb8894ff62387fe7de5b15d625c95b78c0bcd;p=ceph-ci.git cephadm: eliminate duplication of sections Signed-off-by: Rongqi Sun (cherry picked from commit 0d1596e9275e8ca1b8c09b1490b3e595130aa97b) --- diff --git a/src/pybind/mgr/cephadm/module.py b/src/pybind/mgr/cephadm/module.py index 9b45acaa087..18b813abbea 100644 --- a/src/pybind/mgr/cephadm/module.py +++ b/src/pybind/mgr/cephadm/module.py @@ -1905,9 +1905,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 8705bd71401..9e01dd5f745 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='') @@ -1785,10 +1785,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() @@ -1816,6 +1816,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):