]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: fix bind address regression from CherryPy isolation 69574/head
authorAfreen Misbah <afreen@ibm.com>
Tue, 23 Jun 2026 13:30:22 +0000 (19:00 +0530)
committerAfreen Misbah <afreen@ibm.com>
Tue, 23 Jun 2026 16:59:12 +0000 (22:29 +0530)
The CherryPy isolation refactor (PR #67227) accidentally changed the
dashboard bind address from wildcard (*:8443) to mon_ip:8443. The
get_mgr_ip() replacement was originally only for URI generation, but
the refactor passed the mutated address to CherryPyMgr.mount() as the
actual socket bind address.

This breaks the management gateway when its VIP is not on the same
interface as mon_ip, as the dashboard becomes unreachable on other
interfaces.

Preserve the original wildcard address for binding and only use
get_mgr_ip() for the advertised URI. Add regression test to prevent
future confusion between bind_addr and server_addr.

Fixes: https://tracker.ceph.com/issues/77491
Signed-off-by: Afreen Misbah <afreen@ibm.com>
src/pybind/mgr/dashboard/module.py
src/pybind/mgr/dashboard/tests/test_settings.py

index fffa768575beebfc1ff4fa1262315ae0d5ca83f4..7b7bb3b77de1ea0c3067fd5098f740daacf2bfa3 100644 (file)
@@ -209,6 +209,7 @@ class CherryPyConfig(object):
         self._url_prefix = prepare_url_prefix(self.get_module_option(  # type: ignore
             'url_prefix', default=''))
 
+        bind_addr = server_addr
         if server_addr in ['::', '0.0.0.0']:
             server_addr = self.get_mgr_ip()  # type: ignore
         base_url = build_url(
@@ -217,7 +218,7 @@ class CherryPyConfig(object):
             port=server_port,
         )
         uri = f'{base_url}{self.url_prefix}/'
-        return uri, (server_addr, server_port), ssl_info, config
+        return uri, (bind_addr, server_port), ssl_info, config
 
     def await_configuration(self):
         """
index d6c94b6b0b8ba9956018aa3e44f405ce615c838c..17dad55040095a2a52decab504dff28c596606a8 100644 (file)
@@ -2,11 +2,13 @@
 
 import errno
 import unittest
+from unittest.mock import MagicMock
 
 from mgr_module import ERROR_MSG_EMPTY_INPUT_FILE
 
 from .. import settings
 from ..controllers.settings import Settings as SettingsController
+from ..module import CherryPyConfig
 from ..settings import Settings, handle_option_command
 from ..tests import ControllerTestCase, KVStoreMockMixin
 
@@ -125,6 +127,33 @@ class SettingsTest(unittest.TestCase, KVStoreMockMixin):
         self.assertEqual(str(ctx.exception),
                          "type object 'Options' has no attribute 'NON_EXISTENT_OPTION'")
 
+    def _setup_cherrypy_config(self, server_addr, server_port):
+        obj = CherryPyConfig()
+        config_map = {
+            'server_addr': server_addr,
+            'ssl': False,
+            'server_port': server_port
+        }
+        obj.get_localized_module_option = MagicMock(
+            side_effect=lambda key, default=None: config_map.get(key, default))
+        obj.get_mgr_ip = MagicMock(return_value='192.168.1.10')
+        obj.get_module_option = MagicMock(return_value='')
+        obj.get_mgr_id = MagicMock(return_value='test')
+        obj.module_name = 'dashboard'
+        obj.log = MagicMock()
+        obj.update_cherrypy_config = MagicMock()
+        return obj
+
+    def test_wildcard_bind_addr_preserved(self):
+        obj = self._setup_cherrypy_config('::', 8080)
+        _, bind_addr, _, _ = obj._configure()  # pylint: disable=protected-access
+        self.assertEqual(bind_addr, ('::', 8080))
+
+    def test_wildcard_bind_addr_preserved_ipv4(self):
+        obj = self._setup_cherrypy_config('0.0.0.0', 8443)
+        _, bind_addr, _, _ = obj._configure()  # pylint: disable=protected-access
+        self.assertEqual(bind_addr, ('0.0.0.0', 8443))
+
 
 class SettingsControllerTest(ControllerTestCase, KVStoreMockMixin):
     @classmethod