]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
cephadm: set Grafana http_addr to 0.0.0.0 when unset 69080/head
authorKobi Ginon <kginon@redhat.com>
Mon, 25 May 2026 12:38:34 +0000 (15:38 +0300)
committerKobi Ginon <kginon@redhat.com>
Fri, 5 Jun 2026 16:32:56 +0000 (19:32 +0300)
Grafana 11.1+ rejects non-literal http_addr values (e.g. localhost)
in grafana-apiserver. Use 0.0.0.0 by default; stop bracket-wrapping
IPv6 addresses in http_addr.
Fixes: https://tracker.ceph.com/issues/75365
Signed-off-by: Kobi Ginon <kginon@redhat.com>
src/pybind/mgr/cephadm/services/monitoring.py
src/pybind/mgr/cephadm/tests/services/test_monitoring.py

index 86f0aa0a8e88ef05ed84c18e98d65db7c6b7be60..e3fd676e22cefcd2f84b2c2456d66ecf64c51e45 100644 (file)
@@ -2,7 +2,6 @@ import errno
 import logging
 import os
 from typing import List, Any, Tuple, Dict, Optional, cast, TYPE_CHECKING
-import ipaddress
 import time
 import requests
 
@@ -74,8 +73,15 @@ class GrafanaService(CephadmService):
             if ip_to_bind_to:
                 daemon_spec.port_ips = {str(grafana_port): ip_to_bind_to}
                 grafana_ip = ip_to_bind_to
-                if ipaddress.ip_network(grafana_ip).version == 6:
-                    grafana_ip = f"[{grafana_ip}]"
+
+        if not grafana_ip:
+            # Grafana 11.1+ validates http_addr with net.ParseIP; hostnames such as
+            # localhost fail in grafana-apiserver. Use a literal address (bind all IPv4).
+            # Check if the primary manager or orchestrator is configured for IPv6
+            if self.mgr.get_mgr_ip().startswith('::') or ':' in self.mgr.get_mgr_ip():
+                grafana_ip = '::'
+            else:
+                grafana_ip = '0.0.0.0'
 
         domain = self.mgr.get_fqdn(daemon_spec.host)
         mgmt_gw_ips = []
index 57a9d8a3da1d58aed6d1c17429ffa10617ecb609..d582b07863c49586f5313032d9e11494bd91bd82 100644 (file)
@@ -1329,7 +1329,7 @@ class TestMonitoring:
                           cert_file = /etc/grafana/certs/cert_file
                           cert_key = /etc/grafana/certs/cert_key
                           http_port = 3000
-                          http_addr = 
+                          http_addr = ::
                           root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana/
                           serve_from_sub_path = true
                         [snapshots]
@@ -1490,7 +1490,7 @@ class TestMonitoring:
                           cert_file = /etc/grafana/certs/cert_file
                           cert_key = /etc/grafana/certs/cert_key
                           http_port = 3000
-                          http_addr = 
+                          http_addr = ::
                           root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana/
                           serve_from_sub_path = true
                         [snapshots]
@@ -1590,7 +1590,7 @@ class TestMonitoring:
                           cert_file = /etc/grafana/certs/cert_file
                           cert_key = /etc/grafana/certs/cert_key
                           http_port = 3000
-                          http_addr = 
+                          http_addr = ::
                         [snapshots]
                           external_enabled = false
                         [security]
@@ -1681,6 +1681,7 @@ class TestMonitoring:
                 )
 
     @patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}'))
+    @patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '192.0.2.1')
     def test_grafana_initial_admin_pw(self, cephadm_module: CephadmOrchestrator):
         with with_host(cephadm_module, 'test'):
             with with_service(cephadm_module, ServiceSpec('mgr')) as _, \
@@ -1705,7 +1706,7 @@ class TestMonitoring:
                                     '  cert_file = /etc/grafana/certs/cert_file\n'
                                     '  cert_key = /etc/grafana/certs/cert_key\n'
                                     '  http_port = 3000\n'
-                                    '  http_addr = \n'
+                                    '  http_addr = 0.0.0.0\n'
                                     '[snapshots]\n'
                                     '  external_enabled = false\n'
                                     '[security]\n'
@@ -1750,6 +1751,33 @@ class TestMonitoring:
                             }}, ['certificate_source: cephadm-signed', 'secure_monitoring_stack:False'])
 
     @patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}'))
+    @patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '192.0.2.1')
+    def test_grafana_http_addr_binds_all_by_default_ipv4(self, cephadm_module: CephadmOrchestrator):
+        grafana_svc = service_registry.get_service('grafana')
+        with with_host(cephadm_module, 'test'):
+            with with_service(cephadm_module, GrafanaSpec()):
+                ini = grafana_svc.generate_grafana_ini(
+                    CephadmDaemonDeploySpec('test', 'daemon', 'grafana'),
+                    mgmt_gw_enabled=False,
+                    oauth2_enabled=False,
+                )
+                assert 'http_addr = 0.0.0.0' in ini
+
+    @patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}'))
+    @patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '1::4')
+    def test_grafana_http_addr_binds_all_by_default_ipv6(self, cephadm_module: CephadmOrchestrator):
+        grafana_svc = service_registry.get_service('grafana')
+        with with_host(cephadm_module, 'test'):
+            with with_service(cephadm_module, GrafanaSpec()):
+                ini = grafana_svc.generate_grafana_ini(
+                    CephadmDaemonDeploySpec('test', 'daemon', 'grafana'),
+                    mgmt_gw_enabled=False,
+                    oauth2_enabled=False,
+                )
+                assert 'http_addr = ::' in ini
+
+    @patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}'))
+    @patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '192.0.2.1')
     def test_grafana_no_anon_access(self, cephadm_module: CephadmOrchestrator):
         # with anonymous_access set to False, expecting the [auth.anonymous] section
         # to not be present in the grafana config. Note that we require an initial_admin_password
@@ -1774,7 +1802,7 @@ class TestMonitoring:
                                     '  cert_file = /etc/grafana/certs/cert_file\n'
                                     '  cert_key = /etc/grafana/certs/cert_key\n'
                                     '  http_port = 3000\n'
-                                    '  http_addr = \n'
+                                    '  http_addr = 0.0.0.0\n'
                                     '[snapshots]\n'
                                     '  external_enabled = false\n'
                                     '[security]\n'