MKP 3.2.0 released, fixed bugs when users are deleted and rules without levels are active

This commit is contained in:
2026-03-09 11:25:48 +00:00
parent bf470d5d6c
commit 7f58381fd3
9 changed files with 87 additions and 40 deletions

View File

@@ -2,6 +2,7 @@
# pylint: disable=missing-module-docstring, unused-argument, missing-function-docstring
# pylint: disable=line-too-long
from typing import Final
from collections.abc import Mapping
from typing import NotRequired, TypedDict
@@ -18,6 +19,8 @@ from cmk.agent_based.v2 import (
DiscoveryResult,
)
NO_LEVELS: Final[str] = "no_levels"
class _ItemData(TypedDict):
dbtype: NotRequired[str]
@@ -49,14 +52,18 @@ def check_nextcloud_database(params, section) -> CheckResult:
size = section[key]["size"]
dbtype = section[key]["dbtype"]
version = section[key]["version"]
_level_type, levels = params["levels_database_opcache_hit_rate"]
level_type, levels = params["levels_database_opcache_hit_rate"]
# create graph for opcache hit rate
yield Metric(
"nc_database_opcache_hit_rate", opcache_hit_rate, levels=levels
)
if level_type == NO_LEVELS:
yield Metric("nc_database_opcache_hit_rate", opcache_hit_rate)
state = State.OK
else:
yield Metric(
"nc_database_opcache_hit_rate", opcache_hit_rate, levels=levels
)
state = get_state_lower(levels, opcache_hit_rate)
# create graph for database size
yield Metric("nc_database_size", size)
state = get_state_lower(levels, opcache_hit_rate)
summary = f"PHP OPCache hit rate: {render.percent(opcache_hit_rate)}"
if opcache_hit_rate == 0:
state = State.UNKNOWN

View File

@@ -3,6 +3,7 @@
# pylint: disable=line-too-long, too-many-branches, too-many-locals, too-many-statements
from datetime import datetime
from typing import Final
from cmk.agent_based.v2 import (
AgentSection,
@@ -17,6 +18,7 @@ from cmk.agent_based.v2 import (
DiscoveryResult,
)
NO_LEVELS: Final[str] = "no_levels"
def get_state_upper(levels, value):
warn, crit = levels
@@ -43,8 +45,8 @@ def discover_nextcloud_info(section) -> DiscoveryResult:
def check_nextcloud_info(params, section) -> CheckResult:
for key in section:
if key == "nextcloud":
_level_type, levels_free_space = params["levels_free_space"]
_level_type, levels_number_of_files = params["levels_number_of_files"]
level_type_free_space, levels_free_space = params["levels_free_space"]
level_type_number_of_files, levels_number_of_files = params["levels_number_of_files"]
# update infos are available only from Nextcloud version 28 onwards
try:
last_update = section[key]["last_update"]
@@ -89,19 +91,28 @@ def check_nextcloud_info(params, section) -> CheckResult:
# Create result for free space on disk
# Levels for free space are given in GBytes, we have to adjust this here
warn, crit = levels_free_space
warn = warn * 1024 * 1024 * 1024
crit = crit * 1024 * 1024 * 1024
state = get_state_lower((warn, crit), free_space)
# create graph for free space on disk
yield Metric("nc_free_space", free_space, levels=(warn, crit))
if level_type_free_space != NO_LEVELS:
warn, crit = levels_free_space
warn = warn * 1024 * 1024 * 1024
crit = crit * 1024 * 1024 * 1024
state = get_state_lower((warn, crit), free_space)
# create graph for free space on disk
yield Metric("nc_free_space", free_space, levels=(warn, crit))
else:
# a rule with no levels set is active, assume OK state
state = State.OK
yield Metric("nc_free_space", free_space)
notice = f"Remaining free space on disk: {render.bytes(free_space)}"
if state != State.OK:
yield Result(state=state, notice=notice)
# Create result for number of files
warn, crit = levels_number_of_files
state = get_state_upper((warn, crit), num_files)
if level_type_number_of_files != NO_LEVELS:
warn, crit = levels_number_of_files
state = get_state_upper((warn, crit), num_files)
else:
# a rule with no levels set is active, assume OK state
state = State.OK
notice = f"Number of files: {num_files}"
if state != State.OK:
yield Result(state=state, notice=notice)
@@ -139,14 +150,22 @@ def check_nextcloud_info(params, section) -> CheckResult:
else:
app_versions = ""
# create graphs for number of apps
_level_type, levels = params["levels_apps_with_updates_available"]
level_type, levels = params["levels_apps_with_updates_available"]
yield Metric("nc_num_apps_installed", num_apps_installed)
yield Metric(
"nc_apps_with_updates_available",
num_apps_with_updates_available,
levels=levels,
)
state = get_state_upper(levels, num_apps_with_updates_available)
if level_type != NO_LEVELS:
yield Metric(
"nc_apps_with_updates_available",
num_apps_with_updates_available,
levels=levels,
)
state = get_state_upper(levels, num_apps_with_updates_available)
else:
# a rule with no levels set is active, assume OK state
yield Metric(
"nc_apps_with_updates_available",
num_apps_with_updates_available,
)
state = State.OK
if app_versions == "":
notice = f"Number of installed apps: {num_apps_installed}\nNumber of apps with updates available: {num_apps_with_updates_available}"
else:

View File

@@ -3,7 +3,7 @@
# pylint: disable=line-too-long, too-many-locals
from time import time
from pprint import pprint
from typing import Final
from cmk.agent_based.v2 import (
AgentSection,
@@ -18,6 +18,7 @@ from cmk.agent_based.v2 import (
DiscoveryResult,
)
NO_LEVELS: Final[str] = "no_levels"
def get_state_upper(levels, value):
warn, crit = levels
@@ -43,6 +44,10 @@ def discover_nextcloud_users(section) -> DiscoveryResult:
def check_nextcloud_users(item, params, section) -> CheckResult:
attr = section.get(item)
if not attr:
yield Result(state=State.UNKNOWN, summary="User not found anymore, maybe it has been deleted.")
return
userid = item
quota_used_percent = section[item][0]
quota_used_bytes = section[item][1]
@@ -56,8 +61,8 @@ def check_nextcloud_users(item, params, section) -> CheckResult:
quota_is_set = False
else:
quota_is_set = True
_level_type, levels_quota_used = params["levels_users_quota_used"]
_level_type, levels_free_space = params["levels_users_free_space"]
level_type_quota_used, levels_quota_used = params["levels_users_quota_used"]
level_type_free_space, levels_free_space = params["levels_users_free_space"]
if (last_login_human == "never") or (not quota_is_set):
details = f"User ID is '{userid}', Last login: {last_login_human}"
summary = (
@@ -65,19 +70,29 @@ def check_nextcloud_users(item, params, section) -> CheckResult:
)
else:
# Levels are given in MBytes, we have to adjust this here
warn, crit = levels_free_space
warn = warn * 1024 * 1024
crit = crit * 1024 * 1024
state = get_state_lower((warn, crit), free_space)
if level_type_free_space != NO_LEVELS:
warn, crit = levels_free_space
warn = warn * 1024 * 1024
crit = crit * 1024 * 1024
state = get_state_lower((warn, crit), free_space)
yield Metric("nc_users_free_space", free_space, levels=(warn, crit))
else:
# a rule with no levels set is active, so assume OK state
state = State.OK
yield Metric("nc_users_free_space", free_space)
details = f"User ID is '{userid}'\nLast login: {last_login_human} ({last_login_since} ago)\nFree space: {render.bytes(free_space)}"
summary = f"Used quota of '{display_name}' is {render.percent(quota_used_percent)}, {render.bytes(quota_used_bytes)}/{render.bytes(quota_total_bytes)} used"
notice = f"Remaining free space: {render.bytes(free_space)}"
yield Metric("nc_users_free_space", free_space, levels=(warn, crit))
if state != State.OK:
yield Result(state=state, notice=notice)
yield Metric("nc_users_free_space", free_space, levels=(warn, crit))
yield Metric("nc_users_quota_used", quota_used_percent, levels=levels_quota_used)
state = get_state_upper(levels_quota_used, quota_used_percent)
if level_type_quota_used != NO_LEVELS:
yield Metric("nc_users_quota_used", quota_used_percent, levels=levels_quota_used)
state = get_state_upper(levels_quota_used, quota_used_percent)
else:
# a rule with no levels set is active, so assume OK state
yield Metric("nc_users_quota_used", quota_used_percent)
state = State.OK
yield Result(state=state, summary=summary, details=details)

View File

@@ -4,7 +4,7 @@ catalog: unsorted
license: GPL
distribution: check_mk
description:
Works with Nextcloud version 25/26/27/28/29/30 (use at your own risk with lower versions).
Works with Nextcloud version 25/26/27/28/29/30/31/32 (use at your own risk with lower versions).
Tested only with mariab as underlying database.
You have to use a username/app password combination to get access to the Nextcloud API.
You can create this app password within the personal settings of an administrative user in Nextcloud.

View File

@@ -4,9 +4,9 @@ catalog: unsorted
license: GPL
distribution: check_mk
description:
Works with Nextcloud version 25/26/27/28/29/30 (use at your own risk with lower versions).
Works with Nextcloud version 25/26/27/28/29/30/31/32 (use at your own risk with lower versions).
Tested only with mariab as underlying database.
You have to use a username/app password combination to get access to the Nextcloud API.
You have to use a username/app password combination to get access to the Nextcloud API (including user info).
You can create this app password within the personal settings of an administrative user in Nextcloud.
Got to security settings and create a new app password.
The user must not be secured with 2FA.

View File

@@ -4,7 +4,7 @@ catalog: unsorted
license: GPL
distribution: check_mk
description:
Works with Nextcloud version 25/26/27/28/29/30 (use at your own risk with lower versions).
Works with Nextcloud version 25/26/27/28/29/30/31/32 (use at your own risk with lower versions).
Tested only with mariab as underlying database.
You have to use a username/app password combination to get access to the Nextcloud API.
You can create this app password within the personal settings of an administrative user in Nextcloud.