From eda374af6c7336f9dc4c32afe9b2af3b3e8af869 Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Sat, 20 Jun 2026 07:48:27 +0800 Subject: [PATCH] Avoid root logger setup when SELinux helper is missing When testcloud's has_selinux() runs on systems where the selinuxenabled command is not installed. The FileNotFoundError handler used module-level logging.debug(), which implicitly calls logging.basicConfig() when the root logger has no handlers. That creates a default root StreamHandler. Libraries such as tmt use propagating DEBUG-level loggers with their own filtering, so once the root handler exists, their records also get emitted with Python's default format which clutters CI output e.g. [1], /plans/example discover how: shell summary: 1 test selected provision queued provision.provision tasks #1: default-0 provision.provision task #1: default-0 how: virtual ansible: {} image: fedora:43 progress: downloading... DEBUG:tmt.run.logger0.provision.provision.queue: Run command: qemu-img check /var/tmp/tmt/testcloud/images/Fedora-Cloud-Base-Generic-43-1.6.x86_64.qcow2 DEBUG:tmt.run.logger0.provision.provision.queue: environment: {} DEBUG:tmt.run.logger0.provision.provision.queue: Command event: 2.674e-06 waiting for process to finish DEBUG:tmt.run.logger0.provision.provision.queue: stdout: No errors were found on the image. DEBUG:tmt.run.logger0.provision.provision.queue: stdout: 11441/81920 = 13.97% allocated, 91.29% fragmented, 88.97% compressed clusters DEBUG:tmt.run.logger0.provision.provision.queue: stdout: Image end offset: 583335936 DEBUG:tmt.run.logger0.provision.provision.queue: Command event: 0.00551 waiting for process completed DEBUG:tmt.run.logger0.provision.provision.queue: Command event: 0.00559 waiting for stream readers .... Log through the testcloud.util module logger instead, preserving the existing library-mode NullHandler behavior and avoiding implicit root logger configuration. Add a regression test for the missing selinuxenabled path. [1] https://github.com/coiby/kernel-auto-bisect/actions/runs/27798088731/job/82262170969?pr=5 Assisted-by: Codex:gpt-5.5 --- test/test_util.py | 19 +++++++++++++++++++ testcloud/util.py | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 test/test_util.py diff --git a/test/test_util.py b/test/test_util.py new file mode 100644 index 0000000..7e23556 --- /dev/null +++ b/test/test_util.py @@ -0,0 +1,19 @@ +import logging +from unittest.mock import patch + +from testcloud import util + + +def test_has_selinux_missing_command_does_not_configure_root_logging(): + root_logger = logging.getLogger() + handlers = root_logger.handlers[:] + + try: + root_logger.handlers = [] + + with patch("testcloud.util.subprocess.call", side_effect=FileNotFoundError): + assert util.has_selinux() is False + + assert root_logger.handlers == [] + finally: + root_logger.handlers = handlers diff --git a/testcloud/util.py b/testcloud/util.py index fcdcd2a..6d49e6e 100644 --- a/testcloud/util.py +++ b/testcloud/util.py @@ -132,8 +132,8 @@ def has_selinux() -> bool: selinux_active = subprocess.call(["selinuxenabled"]) return not bool(selinux_active) except FileNotFoundError: - logging.debug("selinuxenabled is not present (libselinux-utils package missing?)") - logging.debug("Assuming selinux is not installed and therefore disabled") + log.debug("selinuxenabled is not present (libselinux-utils package missing?)") + log.debug("Assuming selinux is not installed and therefore disabled") return False