]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/cephadm: try to get FQDN for active instance 46787/head
authorTatjana Dehler <tdehler@suse.com>
Mon, 16 May 2022 13:05:37 +0000 (15:05 +0200)
committerAdam King <adking@redhat.com>
Tue, 21 Jun 2022 22:34:11 +0000 (18:34 -0400)
Fixes: https://tracker.ceph.com/issues/55674
Signed-off-by: Tatjana Dehler <tdehler@suse.com>
(cherry picked from commit d0385e030b391f588b4ec0dc707d5d46778a2aaa)

Conflicts:
src/pybind/mgr/cephadm/services/monitoring.py
src/pybind/mgr/cephadm/tests/test_services.py

src/pybind/mgr/cephadm/services/monitoring.py
src/pybind/mgr/cephadm/tests/fixtures.py
src/pybind/mgr/cephadm/tests/test_cephadm.py
src/pybind/mgr/cephadm/tests/test_services.py

index 309ab4eb7864f8e1f073d5204c5f54a8914eb15c..a7c820d17fd935129ddcd080f979b56aa61031af 100644 (file)
@@ -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 = {
index bfc0f0b99e7a90344e603ac6ea5b790fb8664937..672d9b44bdaf4947a75e9a6d6777686f0f330741 100644 (file)
@@ -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]
 
index ae17dd3201fe04ac2adc6cf3919068430013a07a..b028f88e555d6c3375377de3d0fd2ebfa3d18329 100644 (file)
@@ -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'):
index b6ab142493b3009d42977a8aeeded2161ae22bab..7204514247294373237eb6ba951e200c59892545 100644 (file)
@@ -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='')