From: Tatjana Dehler Date: Mon, 16 May 2022 13:05:37 +0000 (+0200) Subject: mgr/cephadm: try to get FQDN for active instance X-Git-Tag: v15.2.17~20^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8c59be50b6058ae3919f2187376be8cc393d55de;p=ceph.git mgr/cephadm: try to get FQDN for active instance Fixes: https://tracker.ceph.com/issues/55674 Signed-off-by: Tatjana Dehler (cherry picked from commit d0385e030b391f588b4ec0dc707d5d46778a2aaa) Conflicts: src/pybind/mgr/cephadm/services/monitoring.py src/pybind/mgr/cephadm/tests/test_services.py --- diff --git a/src/pybind/mgr/cephadm/services/monitoring.py b/src/pybind/mgr/cephadm/services/monitoring.py index 309ab4eb7864..a7c820d17fd9 100644 --- a/src/pybind/mgr/cephadm/services/monitoring.py +++ b/src/pybind/mgr/cephadm/services/monitoring.py @@ -1,11 +1,14 @@ +import ipaddress import logging import os +import socket from typing import List, Any, Tuple, Dict from orchestrator import DaemonDescription from ceph.deployment.service_spec import AlertManagerSpec from cephadm.services.cephadmservice import CephadmService, CephadmDaemonSpec from mgr_util import verify_tls, ServerConfigException, create_self_signed_cert +from urllib.parse import urlparse logger = logging.getLogger(__name__) @@ -106,9 +109,21 @@ class AlertmanagerService(CephadmService): proto = None # http: or https: url = mgr_map.get('services', {}).get('dashboard', None) if url: - dashboard_urls.append(url) - proto = url.split('/')[0] - port = url.split('/')[2].split(':')[1] + p_result = urlparse(url.rstrip('/')) + hostname = socket.getfqdn(p_result.hostname) + + try: + ip = ipaddress.ip_address(hostname) + except ValueError: + pass + else: + if ip.version == 6: + hostname = f'[{hostname}]' + + dashboard_urls.append( + f'{p_result.scheme}://{hostname}:{p_result.port}{"/" if not p_result.path.startswith("/") else ""}{p_result.path}') + proto = p_result.scheme + port = p_result.port # scan all mgrs to generate deps and to get standbys too. # assume that they are all on the same port as the active mgr. for dd in self.mgr.cache.get_daemons_by_service('mgr'): @@ -120,7 +135,7 @@ class AlertmanagerService(CephadmService): if dd.daemon_id == self.mgr.get_mgr_id(): continue addr = self._inventory_get_fqdn(dd.hostname) - dashboard_urls.append('%s//%s:%s/' % (proto, addr.split(':')[0], + dashboard_urls.append('%s://%s:%s/' % (proto, addr.split(':')[0], port)) context = { diff --git a/src/pybind/mgr/cephadm/tests/fixtures.py b/src/pybind/mgr/cephadm/tests/fixtures.py index bfc0f0b99e7a..672d9b44bdaf 100644 --- a/src/pybind/mgr/cephadm/tests/fixtures.py +++ b/src/pybind/mgr/cephadm/tests/fixtures.py @@ -129,11 +129,16 @@ def assert_rm_service(cephadm, srv_name): @contextmanager -def with_service(cephadm_module: CephadmOrchestrator, spec: ServiceSpec, meth, host: str) -> Iterator[List[str]]: - if spec.placement.is_empty(): +def with_service(cephadm_module: CephadmOrchestrator, spec: ServiceSpec, meth=None, host: str = '') -> Iterator[List[str]]: + if spec.placement.is_empty() and host: spec.placement = PlacementSpec(hosts=[host], count=1) - c = meth(cephadm_module, spec) - assert wait(cephadm_module, c) == f'Scheduled {spec.service_name()} update...' + if meth is not None: + c = meth(cephadm_module, spec) + assert wait(cephadm_module, c) == f'Scheduled {spec.service_name()} update...' + else: + c = cephadm_module.apply([spec]) + assert wait(cephadm_module, c) == [f'Scheduled {spec.service_name()} update...'] + specs = [d.spec for d in wait(cephadm_module, cephadm_module.describe_service())] assert spec in specs @@ -141,7 +146,8 @@ def with_service(cephadm_module: CephadmOrchestrator, spec: ServiceSpec, meth, h dds = wait(cephadm_module, cephadm_module.list_daemons()) own_dds = [dd for dd in dds if dd.service_name() == spec.service_name()] - assert own_dds + if host and spec.service_type != 'osd': + assert own_dds yield [dd.name() for dd in own_dds] diff --git a/src/pybind/mgr/cephadm/tests/test_cephadm.py b/src/pybind/mgr/cephadm/tests/test_cephadm.py index ae17dd3201fe..b028f88e555d 100644 --- a/src/pybind/mgr/cephadm/tests/test_cephadm.py +++ b/src/pybind/mgr/cephadm/tests/test_cephadm.py @@ -700,6 +700,7 @@ class TestCephadm(object): ) @mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('{}')) @mock.patch("cephadm.services.cephadmservice.RgwService.create_realm_zonegroup_zone", lambda _, __, ___: None) + @mock.patch("mgr_module.MgrModule.get", lambda _, __: {"services": {"dashboard": "http://192.168.0.123:8080"}}) def test_daemon_add(self, spec: ServiceSpec, meth, cephadm_module): with with_host(cephadm_module, 'test'): with with_daemon(cephadm_module, spec, meth, 'test'): @@ -865,6 +866,7 @@ class TestCephadm(object): ) @mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('{}')) @mock.patch("cephadm.services.cephadmservice.RgwService.create_realm_zonegroup_zone", lambda _, __, ___: None) + @mock.patch("mgr_module.MgrModule.get", lambda _, __: {"services": {"dashboard": "http://192.168.0.123:8080"}}) 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'): diff --git a/src/pybind/mgr/cephadm/tests/test_services.py b/src/pybind/mgr/cephadm/tests/test_services.py index b6ab142493b3..720451424729 100644 --- a/src/pybind/mgr/cephadm/tests/test_services.py +++ b/src/pybind/mgr/cephadm/tests/test_services.py @@ -1,6 +1,8 @@ import pytest +import json +from textwrap import dedent -from unittest.mock import MagicMock, call +from unittest.mock import MagicMock, call, patch from cephadm.services.cephadmservice import MonService, MgrService, MdsService, RgwService, \ RbdMirrorService, CrashService, CephadmService, AuthEntity @@ -9,7 +11,9 @@ from cephadm.services.nfs import NFSService from cephadm.services.osd import RemoveUtil, OSDRemovalQueue, OSDService, OSD, NotFoundError from cephadm.services.monitoring import GrafanaService, AlertmanagerService, PrometheusService, \ NodeExporterService -from ceph.deployment.service_spec import IscsiServiceSpec +from cephadm.module import CephadmOrchestrator +from ceph.deployment.service_spec import IscsiServiceSpec, AlertManagerSpec +from cephadm.tests.fixtures import cephadm_module, with_host, with_service from orchestrator import OrchestratorError @@ -139,3 +143,141 @@ class TestCephadmService: cephadm_services[daemon_type].get_auth_entity("id1", "host") cephadm_services[daemon_type].get_auth_entity("id1", "") cephadm_services[daemon_type].get_auth_entity("id1") + + +class TestMonitoring: + def _get_config(self, url: str) -> str: + return f""" + # This file is generated by cephadm. + # See https://prometheus.io/docs/alerting/configuration/ for documentation. + + global: + resolve_timeout: 5m + + route: + receiver: 'default' + routes: + - group_by: ['alertname'] + group_wait: 10s + group_interval: 10s + repeat_interval: 1h + receiver: 'ceph-dashboard' + + receivers: + - name: 'default' + webhook_configs: + - name: 'ceph-dashboard' + webhook_configs: + - url: '{url}/api/prometheus_receiver' + """ + + @patch("cephadm.module.CephadmOrchestrator._run_cephadm") + @patch("mgr_module.MgrModule.get") + def test_alertmanager_config(self, mock_get, _run_cephadm, + cephadm_module: CephadmOrchestrator): + _run_cephadm.return_value = ('{}', '', 0) + mock_get.return_value = {"services": {"dashboard": "http://[::1]:8080"}} + + with with_host(cephadm_module, 'test'): + with with_service(cephadm_module, AlertManagerSpec()): + y = dedent(self._get_config('http://localhost:8080')).lstrip() + _run_cephadm.assert_called_with( + 'test', + 'alertmanager.test', + 'deploy', + [ + '--name', 'alertmanager.test', + '--config-json', '-', + ], + stdin=json.dumps({"files": {"alertmanager.yml": y}, "peers": []}), + image='') + + @patch("cephadm.module.CephadmOrchestrator._run_cephadm") + @patch("mgr_module.MgrModule.get") + def test_alertmanager_config_v6(self, mock_get, _run_cephadm, + cephadm_module: CephadmOrchestrator): + dashboard_url = "http://[2001:db8:4321:0000:0000:0000:0000:0000]:8080" + _run_cephadm.return_value = ('{}', '', 0) + mock_get.return_value = {"services": {"dashboard": dashboard_url}} + + with with_host(cephadm_module, 'test'): + with with_service(cephadm_module, AlertManagerSpec()): + y = dedent(self._get_config(dashboard_url)).lstrip() + _run_cephadm.assert_called_with( + 'test', + 'alertmanager.test', + 'deploy', + [ + '--name', 'alertmanager.test', + '--config-json', '-', + ], + stdin=json.dumps({"files": {"alertmanager.yml": y}, "peers": []}), + image='') + + @patch("cephadm.module.CephadmOrchestrator._run_cephadm") + @patch("mgr_module.MgrModule.get") + @patch("socket.getfqdn") + def test_alertmanager_config_v6_fqdn(self, mock_getfqdn, mock_get, _run_cephadm, + cephadm_module: CephadmOrchestrator): + _run_cephadm.return_value = ('{}', '', 0) + mock_getfqdn.return_value = "mgr.test.fqdn" + mock_get.return_value = {"services": { + "dashboard": "http://[2001:db8:4321:0000:0000:0000:0000:0000]:8080"}} + + with with_host(cephadm_module, 'test'): + with with_service(cephadm_module, AlertManagerSpec()): + y = dedent(self._get_config("http://mgr.test.fqdn:8080")).lstrip() + _run_cephadm.assert_called_with( + 'test', + 'alertmanager.test', + 'deploy', + [ + '--name', 'alertmanager.test', + '--config-json', '-', + ], + stdin=json.dumps({"files": {"alertmanager.yml": y}, "peers": []}), + image='') + + @patch("cephadm.module.CephadmOrchestrator._run_cephadm") + @patch("mgr_module.MgrModule.get") + def test_alertmanager_config_v4(self, mock_get, _run_cephadm, cephadm_module: CephadmOrchestrator): + dashboard_url = "http://192.168.0.123:8080" + _run_cephadm.return_value = ('{}', '', 0) + mock_get.return_value = {"services": {"dashboard": dashboard_url}} + + with with_host(cephadm_module, 'test'): + with with_service(cephadm_module, AlertManagerSpec()): + y = dedent(self._get_config(dashboard_url)).lstrip() + _run_cephadm.assert_called_with( + 'test', + 'alertmanager.test', + 'deploy', + [ + '--name', 'alertmanager.test', + '--config-json', '-', + ], + stdin=json.dumps({"files": {"alertmanager.yml": y}, "peers": []}), + image='') + + @patch("cephadm.module.CephadmOrchestrator._run_cephadm") + @patch("mgr_module.MgrModule.get") + @patch("socket.getfqdn") + def test_alertmanager_config_v4_fqdn(self, mock_getfqdn, mock_get, _run_cephadm, + cephadm_module: CephadmOrchestrator): + _run_cephadm.return_value = ('{}', '', 0) + mock_getfqdn.return_value = "mgr.test.fqdn" + mock_get.return_value = {"services": {"dashboard": "http://192.168.0.123:8080"}} + + with with_host(cephadm_module, 'test'): + with with_service(cephadm_module, AlertManagerSpec()): + y = dedent(self._get_config("http://mgr.test.fqdn:8080")).lstrip() + _run_cephadm.assert_called_with( + 'test', + 'alertmanager.test', + 'deploy', + [ + '--name', 'alertmanager.test', + '--config-json', '-', + ], + stdin=json.dumps({"files": {"alertmanager.yml": y}, "peers": []}), + image='')