]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/cephadm: Control cephadm.log messages based on a new mgr logging level flag
authorAshwin M. Joshi <ashjosh1@in.ibm.com>
Tue, 10 Feb 2026 06:29:49 +0000 (11:59 +0530)
committerAshwin M. Joshi <ashjosh1@in.ibm.com>
Wed, 11 Feb 2026 10:19:24 +0000 (15:49 +0530)
Fixes: https://tracker.ceph.com/issues/74872
Signed-off-by: Ashwin M. Joshi <ashjosh1@in.ibm.com>
src/cephadm/cephadm.py
src/cephadm/cephadmlib/context.py
src/cephadm/cephadmlib/logging.py
src/pybind/mgr/cephadm/module.py
src/pybind/mgr/cephadm/serve.py
src/pybind/mgr/cephadm/tests/test_cephadm.py

index 4e255e551656bf9e793c3bfa7916937c0730adf9..3116a4fc6ed5a9cf84b9f5c18d7d7a1849980b44 100755 (executable)
@@ -4638,6 +4638,11 @@ def _get_parser():
         action='store_true',
         default=False,
         help='Do not run containers with --cgroups=split (currently only relevant when using podman)')
+    parser.add_argument(
+        '--logging-level',
+        choices=['info', 'debug', 'error', 'warning'],
+        default='debug',
+        help='Tunable log level for cephadm binary: info, debug, error, warning (default: debug)')
 
     subparsers = parser.add_subparsers(help='sub-command')
 
index 3411c199ebb689a850c667704eabb2166be0ae1f..502d2c239c7038f9087d334adaa022065deb46c8 100644 (file)
@@ -31,6 +31,7 @@ class BaseConfig:
         self.memory_request: Optional[int] = None
         self.memory_limit: Optional[int] = None
         self.log_to_journald: Optional[bool] = None
+        self.logging_level: str = 'debug'
 
         self.container_init: bool = CONTAINER_INIT
         # FIXME(refactor) : should be Optional[ContainerEngine]
index f5893d3a51d1fe77ae4610ca13bafaa9e91b9a89..dd8758b7423320013e7651a45e7124bebd5ec62e 100644 (file)
@@ -173,7 +173,8 @@ def _copy(obj: Any) -> Any:
 
 
 def _complete_logging_config(
-    interactive: bool, destinations: Optional[List[str]]
+    interactive: bool, destinations: Optional[List[str]],
+    logging_level: str = 'debug',
 ) -> Dict[str, Any]:
     """Return a logging configuration dict, based on the runtime parameters
     cephadm was invoked with.
@@ -183,6 +184,10 @@ def _complete_logging_config(
     if interactive:
         lc = _copy(_interactive_logging_config)
 
+    # Override the default 'debug' level with the logging level cephadm received
+    if logging_level == 'info':
+        lc['handlers']['log_file']['level'] = 'INFO'
+
     handlers = lc['loggers']['']['handlers']
     if not destinations:
         handlers.append(LogDestination.file.value)
@@ -206,9 +211,11 @@ def cephadm_init_logging(
     if not os.path.exists(LOG_DIR):
         os.makedirs(LOG_DIR)
 
+    logging_level = getattr(ctx, 'logging_level', 'debug').lower()
     lc = _complete_logging_config(
         any(op in args for op in _INTERACTIVE_CMDS),
         getattr(ctx, 'log_dest', None),
+        logging_level=logging_level,
     )
     logging.config.dictConfig(lc)
 
index c815bbb128798dbb35511bbbc6a44448c91c22b2..d9eea2e529d3904ec16577f6ea9b1912e2e758de 100644 (file)
@@ -499,6 +499,13 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule):
             desc="Destination for cephadm command persistent logging",
             enum_allowed=['file', 'syslog', 'file,syslog'],
         ),
+        Option(
+            'cephadm_binary_logging_level',
+            type='str',
+            default='debug',
+            desc='Logging verbosity for the cephadm binary when invoked by the mgr (e.g. check-host, gather-facts).',
+            enum_allowed=['info', 'debug', 'error', 'warning']
+        ),
         Option(
             'oob_default_addr',
             type='str',
@@ -611,6 +618,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule):
             self.certificate_automated_rotation_enabled = False
             self.certificate_check_debug_mode = False
             self.certificate_check_period = 0
+            self.cephadm_binary_logging_level = 'debug'
 
         self.notify(NotifyType.mon_map, None)
         self.config_notify()
index 3f1c63bcda114821d6aecda836a2ebfbd1dcb017..376dcc478ff6d457dea55385665dd43144a5d9f2 100644 (file)
@@ -1719,6 +1719,9 @@ class CephadmServe:
         if image:
             final_args.extend(['--image', image])
 
+        cephadm_log_level = str(self.mgr.get_module_option('cephadm_binary_logging_level') or 'debug')
+        final_args.extend(['--logging-level', cephadm_log_level])
+
         if not self.mgr.container_init:
             final_args += ['--no-container-init']
 
index a9d40ec7f07d5020f23226bc3d6b141cf62a02ab..dea24bd11ce03312996692623c4b25b6c0f66e12 100644 (file)
@@ -2917,3 +2917,90 @@ Traceback (most recent call last):
                 assert wait(cephadm_module, c) == ['Scheduled osd.foo update...']
 
                 cephadm_module.set_osd_spec('osd.foo', ['1'])
+
+
+class TestCephadmBinaryLoggingLevel:
+    """Test that host-status / cephadm binary logs are suppressed or shown based on
+    mgr/cephadm/cephadm_binary_logging_level (info vs debug).
+    """
+    @mock.patch("cephadm.ssh.SSHManager._remote_connection")
+    @mock.patch("cephadm.ssh.SSHManager._execute_command")
+    @mock.patch("cephadm.ssh.SSHManager._check_execute_command")
+    def test_check_host_invokes_cephadm_with_logging_level_info(
+        self, check_execute_command, execute_command, remote_connection, cephadm_module
+    ):
+        """When cephadm_binary_logging_level is info, check-host must be invoked with
+        --logging-level info so host-status DEBUG logs are suppressed in cephadm.log.
+        """
+        remote_connection.side_effect = async_side_effect(mock.Mock())
+        captured_commands = []
+
+        async def capture_execute(host, cmd, *args, **kwargs):
+            if hasattr(cmd, 'args') and 'check-host' in cmd.args:
+                captured_commands.append(cmd)
+            return ('', '', 0)
+
+        execute_command.side_effect = capture_execute
+
+        orig_get = cephadm_module.get_module_option
+
+        def get_opt(key, default=None):
+            if key == 'cephadm_binary_logging_level':
+                return 'info'
+            return orig_get(key, default)
+
+        with mock.patch.object(cephadm_module, 'get_module_option', side_effect=get_opt):
+            with with_host(cephadm_module, 'test'):
+                pass
+
+        check_host_cmds = [c for c in captured_commands if 'check-host' in c.args]
+        assert len(check_host_cmds) >= 1, 'expected at least one check-host invocation'
+        cmd = check_host_cmds[0]
+        assert '--logging-level' in cmd.args, (
+            'cephadm should be called with --logging-level when level is info'
+        )
+        idx = cmd.args.index('--logging-level')
+        assert cmd.args[idx + 1] == 'info', (
+            'host-status logs should be suppressed with logging-level info'
+        )
+
+    @mock.patch("cephadm.ssh.SSHManager._remote_connection")
+    @mock.patch("cephadm.ssh.SSHManager._execute_command")
+    @mock.patch("cephadm.ssh.SSHManager._check_execute_command")
+    def test_check_host_invokes_cephadm_with_logging_level_debug(
+        self, check_execute_command, execute_command, remote_connection, cephadm_module
+    ):
+        """When cephadm_binary_logging_level is debug, check-host must be invoked with
+        --logging-level debug so current (verbose) host-status logging continues.
+        """
+        remote_connection.side_effect = async_side_effect(mock.Mock())
+        captured_commands = []
+
+        async def capture_execute(host, cmd, *args, **kwargs):
+            if hasattr(cmd, 'args') and 'check-host' in cmd.args:
+                captured_commands.append(cmd)
+            return ('', '', 0)
+
+        execute_command.side_effect = capture_execute
+
+        orig_get = cephadm_module.get_module_option
+
+        def get_opt(key, default=None):
+            if key == 'cephadm_binary_logging_level':
+                return 'debug'
+            return orig_get(key, default)
+
+        with mock.patch.object(cephadm_module, 'get_module_option', side_effect=get_opt):
+            with with_host(cephadm_module, 'test'):
+                pass
+
+        check_host_cmds = [c for c in captured_commands if 'check-host' in c.args]
+        assert len(check_host_cmds) >= 1, 'expected at least one check-host invocation'
+        cmd = check_host_cmds[0]
+        assert '--logging-level' in cmd.args, (
+            'cephadm should be called with --logging-level when level is debug'
+        )
+        idx = cmd.args.index('--logging-level')
+        assert cmd.args[idx + 1] == 'debug', (
+            'host-status logs should not be suppressed with logging-level debug'
+        )