Skip to content

Commit

Permalink
15342 FIX systemd_units_*_summary: Support units without description
Browse files Browse the repository at this point in the history
The parser assumed that there is always a description, but systemd seems
to be okay with units without description.

The units were still detected but some service details were missing, for
example how long the service was in a temporary state.

Change-Id: I424e4dedb7144668f885ec1574b74fda135d7315
  • Loading branch information
BenediktSeidl committed Jan 13, 2025
1 parent 74a5676 commit 2d05656
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 1 deletion.
18 changes: 18 additions & 0 deletions .werks/15342.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[//]: # (werk v2)
# systemd_units_*_summary: Support units without description

key | value
---------- | ---
date | 2024-08-20T13:41:37+00:00
version | 2.3.0p25
class | fix
edition | cre
component | checks
level | 1
compatible | yes

The parser assumed that there is always a description, but systemd seems to be
okay with units without description.

The units were still detected but some service details were missing, for example
how long the service was in a temporary state.
13 changes: 12 additions & 1 deletion cmk/base/plugins/agent_based/systemd_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Copyright (C) 2022 Checkmk GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.
import re
from collections import defaultdict
from collections.abc import Iterable, Iterator, Mapping, Sequence
from dataclasses import dataclass
Expand Down Expand Up @@ -303,6 +304,12 @@ def _is_service_entry(entry: Sequence[Sequence[str]]) -> bool:
return unit.endswith(".service")


SERVICE_REGEX = re.compile(
r".+\.(service|socket|device|mount|automount|swap|target|path|timer|slice|scope)$"
)
# hopefully all possible unit types as described in https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html#Description


def _is_new_entry(line: Sequence[str], entry: list[Sequence[str]]) -> bool:
# First check if we're not looking at a "Triggers" section.
# It looks like the beginning of a new status entry, e.g.:
Expand All @@ -313,7 +320,11 @@ def _is_new_entry(line: Sequence[str], entry: list[Sequence[str]]) -> bool:
return False
if elem[0] not in _STATUS_SYMBOLS:
break
return (line[0] in _STATUS_SYMBOLS) and (len(line) > 3) and ("." in line[1])
return (
(line[0] in _STATUS_SYMBOLS)
and (len(line) >= 2)
and (bool(SERVICE_REGEX.match(str(line[1]))))
)


def _parse_status(source: Iterator[Sequence[str]]) -> Mapping[str, UnitStatus]:
Expand Down
45 changes: 45 additions & 0 deletions tests/unit/cmk/base/plugins/agent_based/test_systemd_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -1291,3 +1291,48 @@ def test_reloading() -> None:
summary="Service 'testing' reloading for: 53 seconds (warn/crit at 30 seconds/1 minute 0 seconds)",
),
]


def test_broken_parsing_without_unit_description() -> None:
pre_pre_string_table = """
<<<systemd_units>>>
[list-unit-files]
testing.service enabled enabled
systemd-user-sessions.service static -
[status]
● klapp-0285
State: running
Jobs: 1 queued
Failed: 0 units
Since: Mon 2024-08-19 07:09:27 CEST; 1 day 4h ago
CGroup: /
├─sys-fs-fuse-connections.mount
● systemd-user-sessions.service - Permit User Sessions
Loaded: loaded (/lib/systemd/system/systemd-user-sessions.service; static)
Active: active (exited) since Mon 2024-08-19 07:09:30 CEST; 1 day 4h ago
Docs: man:systemd-user-sessions.service(8)
Main PID: 1397 (code=exited, status=0/SUCCESS)
CPU: 6ms
↻ testing.service
Loaded: loaded (/etc/systemd/system/testing.service; enabled; vendor preset: enabled)
Active: reloading (reload) since Tue 2024-08-20 11:49:32 CEST; 53s ago
Process: 1727884 ExecStartPre=/usr/bin/sleep 75 (code=exited, status=0/SUCCESS)
Main PID: 1728726 (sleep); Control PID: 1729357 (sleep)
Tasks: 2 (limit: 38119)
Memory: 360.0K
CPU: 8ms
CGroup: /system.slice/testing.service
├─1728726 /usr/bin/sleep 90000
└─1729357 /usr/bin/sleep 65
[all]
testing.service loaded reloading reload reload testing.service
systemd-user-sessions.service loaded active exited Permit User Sessions
"""

string_table = [l.split(" ") for l in pre_pre_string_table.split("\n")]
parsed = parse(string_table)
assert parsed is not None
assert parsed.services["testing"].time_since_change == timedelta(seconds=53)

0 comments on commit 2d05656

Please sign in to comment.