From a8f1cf2edb0ef5b48632af8da9577c8a42a6ff60 Mon Sep 17 00:00:00 2001 From: Sebastian Wagner Date: Wed, 21 Jul 2021 10:45:51 +0200 Subject: [PATCH] mgr/cephadm: Fix haproxy not being recognized as a proper daemon Turns out daemon types != service types: cephadm [WRN] Found unknown service type haproxy on host smithi019 cephadm [WRN] Found unknown service type keepalived on host smithi019 leading to `self.mgr.cache.get_daemons_by_service(spec.service_name())` not returning any daemons. Fixes: https://tracker.ceph.com/issues/51311 Signed-off-by: Sebastian Wagner --- src/pybind/mgr/cephadm/serve.py | 4 ++-- src/pybind/mgr/cephadm/services/ingress.py | 8 +++++++- src/pybind/mgr/cephadm/tests/test_cephadm.py | 14 ++++++++++---- src/pybind/mgr/orchestrator/__init__.py | 2 +- src/pybind/mgr/orchestrator/_interface.py | 4 ++++ 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/pybind/mgr/cephadm/serve.py b/src/pybind/mgr/cephadm/serve.py index 275e541828d..12bda65e590 100644 --- a/src/pybind/mgr/cephadm/serve.py +++ b/src/pybind/mgr/cephadm/serve.py @@ -405,8 +405,8 @@ class CephadmServe: if v: setattr(sd, k, str_to_datetime(d[k])) sd.daemon_type = d['name'].split('.')[0] - if sd.daemon_type not in ServiceSpec.KNOWN_SERVICE_TYPES: - logger.warning(f"Found unknown service type {sd.daemon_type} on host {host}") + if sd.daemon_type not in orchestrator.KNOWN_DAEMON_TYPES: + logger.warning(f"Found unknown daemon type {sd.daemon_type} on host {host}") continue sd.daemon_id = '.'.join(d['name'].split('.')[1:]) diff --git a/src/pybind/mgr/cephadm/services/ingress.py b/src/pybind/mgr/cephadm/services/ingress.py index f78f558a2d8..9c49cc6932d 100644 --- a/src/pybind/mgr/cephadm/services/ingress.py +++ b/src/pybind/mgr/cephadm/services/ingress.py @@ -65,7 +65,8 @@ class IngressService(CephService): spec = cast(IngressSpec, self.mgr.spec_store[daemon_spec.service_name].spec) assert spec.backend_service if spec.backend_service not in self.mgr.spec_store: - raise RuntimeError(f'{spec.service_name()} backend service {spec.backend_service} does not exist') + raise RuntimeError( + f'{spec.service_name()} backend service {spec.backend_service} does not exist') backend_spec = self.mgr.spec_store[spec.backend_service].spec daemons = self.mgr.cache.get_daemons_by_service(spec.backend_service) deps = [d.name() for d in daemons] @@ -183,6 +184,11 @@ class IngressService(CephService): password = spec.keepalived_password daemons = self.mgr.cache.get_daemons_by_service(spec.service_name()) + + if not daemons: + raise OrchestratorError( + f'Failed to generate keepalived.conf: No daemons deployed for {spec.service_name()}') + deps = sorted([d.name() for d in daemons if d.daemon_type == 'haproxy']) host = daemon_spec.host diff --git a/src/pybind/mgr/cephadm/tests/test_cephadm.py b/src/pybind/mgr/cephadm/tests/test_cephadm.py index f448499fb00..2daf2ee0798 100644 --- a/src/pybind/mgr/cephadm/tests/test_cephadm.py +++ b/src/pybind/mgr/cephadm/tests/test_cephadm.py @@ -240,6 +240,11 @@ class TestCephadm(object): style='cephadm', fsid='fsid', ), + dict( + name='haproxy.test.bar', + style='cephadm', + fsid='fsid', + ), ]) )) @@ -248,8 +253,7 @@ class TestCephadm(object): with with_host(cephadm_module, 'test'): CephadmServe(cephadm_module)._refresh_host_daemons('test') dds = wait(cephadm_module, cephadm_module.list_daemons()) - assert len(dds) == 1 - assert dds[0].name() == 'rgw.myrgw.foobar' + assert {d.name() for d in dds} == {'rgw.myrgw.foobar', 'haproxy.test.bar'} @mock.patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('[]')) def test_daemon_action(self, cephadm_module: CephadmOrchestrator): @@ -887,7 +891,8 @@ spec: placement=ps) unmanaged_spec = ServiceSpec.from_json(spec.to_json()) unmanaged_spec.unmanaged = True - cephadm_module._mon_command_mock_mgr_module_ls = lambda *args: json.dumps({'enabled_modules': []}) + cephadm_module._mon_command_mock_mgr_module_ls = lambda *args: json.dumps({ + 'enabled_modules': []}) with with_service(cephadm_module, unmanaged_spec): c = cephadm_module.add_daemon(spec) @@ -1021,7 +1026,8 @@ spec: @mock.patch("subprocess.run", mock.MagicMock()) def test_apply_save(self, spec: ServiceSpec, meth, cephadm_module: CephadmOrchestrator): with with_host(cephadm_module, 'test'): - cephadm_module._mon_command_mock_mgr_module_ls = lambda *args: json.dumps({'enabled_modules': []}) + cephadm_module._mon_command_mock_mgr_module_ls = lambda *args: json.dumps({ + 'enabled_modules': []}) with with_service(cephadm_module, spec, meth, 'test'): pass diff --git a/src/pybind/mgr/orchestrator/__init__.py b/src/pybind/mgr/orchestrator/__init__.py index d9837e0c081..c901284d3e7 100644 --- a/src/pybind/mgr/orchestrator/__init__.py +++ b/src/pybind/mgr/orchestrator/__init__.py @@ -12,7 +12,7 @@ from ._interface import \ DaemonDescription, DaemonDescriptionStatus, \ OrchestratorEvent, set_exception_subject, \ InventoryHost, DeviceLightLoc, \ - UpgradeStatusSpec, daemon_type_to_service, service_to_daemon_types + UpgradeStatusSpec, daemon_type_to_service, service_to_daemon_types, KNOWN_DAEMON_TYPES import os diff --git a/src/pybind/mgr/orchestrator/_interface.py b/src/pybind/mgr/orchestrator/_interface.py index 16a0b5d9347..ef71c2ed3c1 100644 --- a/src/pybind/mgr/orchestrator/_interface.py +++ b/src/pybind/mgr/orchestrator/_interface.py @@ -736,6 +736,10 @@ def service_to_daemon_types(stype: str) -> List[str]: return mapping[stype] +KNOWN_DAEMON_TYPES: List[str] = list( + sum((service_to_daemon_types(t) for t in ServiceSpec.KNOWN_SERVICE_TYPES), [])) + + class UpgradeStatusSpec(object): # Orchestrator's report on what's going on with any ongoing upgrade def __init__(self) -> None: