Support %p and %P in core dump handler filename

The StarlingX Kubernetes Pod Core Dump Handler now supports both %p
(container PID) and %P (host PID) in the pod annotation for core dump
filenames. Updated parse_core_pattern to handle both specifiers case-
sensitively, ensuring correct PID substitution. Modified kernel core
pattern to pass both %p and %P. This resolves issues with PID mismatches

Test Plan:
PASSED Tested with annotation "/coredump-log/core.%p.%u.%g.%s.%t.%e":
       Verified container PID  in filename
PASSED Tested with annotation "/coredump-log/core.%P.%u.%g.%s.%t.%e":
       Verified host PID in filename.
PASSED Tested with annotation "/coredump-log/core.%p.%P.%u.%g.%s.%t.%e":
       Verified both PIDs  in filename
PASSED Verify coredump generated from host (used kill -s SIGTRAP $(pgrep sleep))
       able to see core.3745094.0.0.5.1744616821.sleep in /var/lib/systemd/coredump/

Closes-Bug: 2106814

Change-Id: Ic06758f09f099bc77a68d0084030c8d860382e15
Signed-off-by: rummadis <ramu.ummadishetty@windriver.com>
This commit is contained in:
rummadis 2025-04-11 06:13:23 -04:00
parent 51b5a94aa5
commit ab051505f5
6 changed files with 37 additions and 26 deletions

View File

@ -1,5 +1,5 @@
################################################################################ ################################################################################
# Copyright (c) 2022 Wind River Systems, Inc. # Copyright (c) 2022,2025 Wind River Systems, Inc.
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
@ -12,7 +12,7 @@ from . import coredump
def main(): def main():
# https://man7.org/linux/man-pages/man5/core.5.html # https://man7.org/linux/man-pages/man5/core.5.html
kwargs = { kwargs = {
'pid': sys.argv[1], # %P 'host_pid': sys.argv[1], # %P
'uid': sys.argv[2], # %u 'uid': sys.argv[2], # %u
'gid': sys.argv[3], # %g 'gid': sys.argv[3], # %g
'signal': sys.argv[4], # %s 'signal': sys.argv[4], # %s
@ -20,6 +20,7 @@ def main():
'comm': sys.argv[6], # %e 'comm': sys.argv[6], # %e
'hostname': sys.argv[7], # %h 'hostname': sys.argv[7], # %h
'comm2': sys.argv[8], # %h 'comm2': sys.argv[8], # %h
'container_pid': sys.argv[9], # %p
} }
coredump.CoreDumpHandler(**kwargs) coredump.CoreDumpHandler(**kwargs)

View File

@ -1,5 +1,5 @@
################################################################################ ################################################################################
# Copyright (c) 2022 Wind River Systems, Inc. # Copyright (c) 2022,2025 Wind River Systems, Inc.
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
@ -71,14 +71,20 @@ def parse_core_pattern(string_core_pattern, **kwargs):
string_core_pattern = splitted_path[-1] string_core_pattern = splitted_path[-1]
LOG.info(f'Parsing core pattern: {string_core_pattern}') LOG.info(f'Parsing core pattern: {string_core_pattern}')
processed_string = string_core_pattern.lower() processed_string = string_core_pattern
processed_string = processed_string.replace('%p', kwargs['pid']) for pattern, value in [
processed_string = processed_string.replace('%u', kwargs['uid']) ('%p', kwargs.get('container_pid')),
processed_string = processed_string.replace('%g', kwargs['gid']) ('%P', kwargs.get('host_pid')),
processed_string = processed_string.replace('%s', kwargs['signal']) ('%u', kwargs.get('uid')),
processed_string = processed_string.replace('%t', kwargs['timestamp']) ('%g', kwargs.get('gid')),
processed_string = processed_string.replace('%h', kwargs['hostname']) ('%s', kwargs.get('signal')),
processed_string = processed_string.replace('%e', kwargs['comm2']) ('%t', kwargs.get('timestamp')),
('%h', kwargs.get('hostname')),
('%e', kwargs.get('comm2'))
]:
if pattern in processed_string:
processed_string = processed_string.replace(pattern, value)
LOG.info(f'Core pattern parsed to {processed_string}') LOG.info(f'Core pattern parsed to {processed_string}')
splitted_path[-1] = processed_string splitted_path[-1] = processed_string

View File

@ -1,5 +1,5 @@
################################################################################ ################################################################################
# Copyright (c) 2022 Wind River Systems, Inc. # Copyright (c) 2022,2025 Wind River Systems, Inc.
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
@ -98,11 +98,14 @@ def _podCoreFile(pid, corefile, annotations_config):
def CoreDumpHandler(**kwargs): def CoreDumpHandler(**kwargs):
pid = kwargs['pid'] pid = kwargs['host_pid']
uid = kwargs['uid'] uid = kwargs['uid']
exe = kwargs['comm'] exe = kwargs['comm']
container_pid = kwargs['container_pid']
LOG.critical("Process %s (%s) of user %s dumped core." % (pid, exe, uid)) LOG.critical(
"Process of External PID %s / Internal PID %s (command:%s) of user %s dumped core" %
(pid, container_pid, exe, uid)
)
pod = _lookupPod(pid) pod = _lookupPod(pid)
if pod: if pod:

View File

@ -1,5 +1,5 @@
################################################################################ ################################################################################
# Copyright (c) 2023 Wind River Systems, Inc. # Copyright (c) 2023,2025 Wind River Systems, Inc.
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
@ -125,7 +125,7 @@ class BaseTestCase(TestCase):
# Values that would come from the invokation of k8s-coredump-handler # Values that would come from the invokation of k8s-coredump-handler
self.input_kwargs = { self.input_kwargs = {
'pid': "999999", # %P 'host_pid': "999999", # %P
'uid': "8", # %u 'uid': "8", # %u
'gid': "7", # %g 'gid': "7", # %g
'signal': "6", # %s 'signal': "6", # %s
@ -133,4 +133,5 @@ class BaseTestCase(TestCase):
'comm': "process_name_for_systemd_handler", # %e 'comm': "process_name_for_systemd_handler", # %e
'hostname': "test_host", # %h 'hostname': "test_host", # %h
'comm2': "process_name_for_k8s_handler", # %e 'comm2': "process_name_for_k8s_handler", # %e
'container_pid': "123456", # %p
} }

View File

@ -1,5 +1,5 @@
################################################################################ ################################################################################
# Copyright (c) 2023 Wind River Systems, Inc. # Copyright (c) 2023,2025 Wind River Systems, Inc.
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
@ -17,12 +17,12 @@ DISK_USAGE = {'total_space': 536870912000, 'used_space': 268435456000, 'free_spa
# Dictionary with test input values and expected values for individual test cases. # Dictionary with test input values and expected values for individual test cases.
ANNOTATIONS_EXAMPLES = [ ANNOTATIONS_EXAMPLES = [
{ {
"starlingx.io/core_pattern": "test.core.%P.%U.%G.%S.%T.%E.%H", # All Upper Case "starlingx.io/core_pattern": "test.core.%P.%p.%u.%g.%s.%t.%e.%h",
"starlingx.io/core_max_size": "200K", # Test Kilobytes and Upper case "starlingx.io/core_max_size": "200K", # Test Kilobytes and Upper case
"starlingx.io/core_compression": "lz4", # Test compression. "starlingx.io/core_compression": "lz4", # Test compression.
"starlingx.io/core_max_used": "20%", # Test maximum used space "starlingx.io/core_max_used": "20%", # Test maximum used space
"starlingx.io/core_min_free": "20%", "starlingx.io/core_min_free": "20%",
"expected_core_pattern": "test.core.999999.8.7.6.1671181200.process_name_for_k8s_handler.test_host", "expected_core_pattern": "test.core.999999.123456.8.7.6.1671181200.process_name_for_k8s_handler.test_host",
"expected_core_max_size": (200.0, config_functions.file_size_properties['k']), "expected_core_max_size": (200.0, config_functions.file_size_properties['k']),
"expected_truncate_value": 0, "expected_truncate_value": 0,
# The value here is 0 because the core_max_used is 20% and the test # The value here is 0 because the core_max_used is 20% and the test
@ -33,14 +33,14 @@ ANNOTATIONS_EXAMPLES = [
{ {
"starlingx.io/core_pattern": "test.core.%p.%u.%g.%s.%t.%e.%h", # All Lower Case "starlingx.io/core_pattern": "test.core.%p.%u.%g.%s.%t.%e.%h", # All Lower Case
"starlingx.io/core_max_size": "20m", # Test Megabytes and Lower case "starlingx.io/core_max_size": "20m", # Test Megabytes and Lower case
"expected_core_pattern": "test.core.999999.8.7.6.1671181200.process_name_for_k8s_handler.test_host", "expected_core_pattern": "test.core.123456.8.7.6.1671181200.process_name_for_k8s_handler.test_host",
"expected_core_max_size": (20.0, config_functions.file_size_properties['m']), "expected_core_max_size": (20.0, config_functions.file_size_properties['m']),
"expected_truncate_value": 20971520, # 20mb in Bytes "expected_truncate_value": 20971520, # 20mb in Bytes
"coredump_file_content": "0123456789012345678901234567890123456789", "coredump_file_content": "0123456789012345678901234567890123456789",
"expected_write_content": "0123456789012345678901234567890123456789", "expected_write_content": "0123456789012345678901234567890123456789",
}, },
{ {
"starlingx.io/core_pattern": "test.core.%P.%u.%G.%s.%t.%E.%h", # Mixed Case "starlingx.io/core_pattern": "test.core.%P.%u.%g.%s.%t.%e.%h", # Mixed Case
"starlingx.io/core_max_size": "2G", # Test Gigabytes "starlingx.io/core_max_size": "2G", # Test Gigabytes
"starlingx.io/core_min_free": "249G", "starlingx.io/core_min_free": "249G",
# The test is setup to have 250gb free space, configuring 249gb as # The test is setup to have 250gb free space, configuring 249gb as
@ -64,14 +64,14 @@ ANNOTATIONS_EXAMPLES = [
{ {
"starlingx.io/core_pattern": "test.core.%p.%u.%g.%s.%t.%e.%h", # All Lower Case "starlingx.io/core_pattern": "test.core.%p.%u.%g.%s.%t.%e.%h", # All Lower Case
"starlingx.io/core_max_size": "10b", # Test bytes and Lower case "starlingx.io/core_max_size": "10b", # Test bytes and Lower case
"expected_core_pattern": "test.core.999999.8.7.6.1671181200.process_name_for_k8s_handler.test_host", "expected_core_pattern": "test.core.123456.8.7.6.1671181200.process_name_for_k8s_handler.test_host",
"expected_core_max_size": (10.0, config_functions.file_size_properties['b']), "expected_core_max_size": (10.0, config_functions.file_size_properties['b']),
"expected_truncate_value": 10, # 10 Bytes "expected_truncate_value": 10, # 10 Bytes
"coredump_file_content": "012345678901234567890123456789", "coredump_file_content": "012345678901234567890123456789",
"expected_write_content": "0123456789", "expected_write_content": "0123456789",
}, },
{ {
"starlingx.io/core_pattern": "/var/log/coredump/test.core.%P.%u.%G.%s.%t.%E.%h", # With path "starlingx.io/core_pattern": "/var/log/coredump/test.core.%P.%u.%g.%s.%t.%e.%h", # With path
"expected_core_pattern": "expected_core_pattern":
"/var/log/coredump/test.core.999999.8.7.6.1671181200.process_name_for_k8s_handler.test_host", "/var/log/coredump/test.core.999999.8.7.6.1671181200.process_name_for_k8s_handler.test_host",
"expected_truncate_value": 0, # No size limit "expected_truncate_value": 0, # No size limit
@ -112,7 +112,7 @@ MOCKED_POD_INFO = f"""
"uid": "{MOCKED_UID}", "uid": "{MOCKED_UID}",
"annotations": "annotations":
{{ {{
"starlingx.io/core_pattern": "test.core.%P.%U.%G.%S.%T.%E.%H", "starlingx.io/core_pattern": "test.core.%P.%u.%g.%s.%t.%e.%h.%p",
"starlingx.io/core_max_size": "200K", "starlingx.io/core_max_size": "200K",
"starlingx.io/core_compression": "lz4", "starlingx.io/core_compression": "lz4",
"starlingx.io/core_max_used": "20%", "starlingx.io/core_max_used": "20%",

View File

@ -13,7 +13,7 @@
# the core dump. # the core dump.
# #
# See systemd-coredump(8) and core(5). # See systemd-coredump(8) and core(5).
kernel.core_pattern=|/usr/bin/k8s-coredump %P %u %g %s %t 9223372036854775808 %h %e kernel.core_pattern=|/usr/bin/k8s-coredump %P %u %g %s %t 9223372036854775808 %h %e %p
# Allow that 16 coredumps are dispatched in parallel by the kernel. We want to # Allow that 16 coredumps are dispatched in parallel by the kernel. We want to
# be able to collect process metadata from /proc/%P/ while processing # be able to collect process metadata from /proc/%P/ while processing