From 82333a2ebcb0b5910c87a7b2e3cb94c55a6cb9cb Mon Sep 17 00:00:00 2001 From: cmk-bonobo Date: Wed, 16 Aug 2023 12:12:13 +0200 Subject: [PATCH] Fixed some misleading information strings --- README.md | 6 +++++- .../plugins/agent_based/nextcloud_database.py | 2 +- .../share/check_mk/checkman/nextcloud_database | 4 ++-- local/share/check_mk/checkman/nextcloud_info | 2 +- local/share/check_mk/checkman/nextcloud_users | 2 +- .../web/plugins/metrics/nextcloud_metrics.py | 2 +- .../plugins/wato/nextcloud_database_rules.py | 2 +- .../web/plugins/wato/nextcloud_params.py | 2 -- .../web/plugins/wato/nextcloud_users_rules.py | 1 + mkp/Nextcloud-2.3.3.mkp | Bin 0 -> 10009 bytes 10 files changed, 13 insertions(+), 10 deletions(-) create mode 100755 mkp/Nextcloud-2.3.3.mkp diff --git a/README.md b/README.md index 860851c..85e8233 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,15 @@ # Nextcloud CheckMK Special Agent -Monitors various aspects of Nextcloud instances like state, quota and disk usage of all users, number of apps with available updates, database cache hit rate and so on. +Monitors various aspects of Nextcloud instances like state, quota and disk usage of all users, number of apps with available updates, database php opcache hit rate and so on. Gives additional information regarding versions of Nextcloud, database, number of storages and active users etc. +Tested with Nextcloud 25/26/27. +Tested only with MySQL/MariaDB as database backend. +Feel free to report other working environments. Version History: -- |Date|Version|Changes| |----|-------|-------| +|2023/08/16|2.3.3|Fixed some misleading info strings regarding database opcache| |2023/08/12|2.3.2|MKP now compatible with CheckMK 2.2| |2023/03/27|2.3.1|Fixed bugs in parameter handling| |2023/03/23|2.2.1|Adjusted parameter handling| diff --git a/local/lib/python3/cmk/base/plugins/agent_based/nextcloud_database.py b/local/lib/python3/cmk/base/plugins/agent_based/nextcloud_database.py index 3765c72..240716a 100644 --- a/local/lib/python3/cmk/base/plugins/agent_based/nextcloud_database.py +++ b/local/lib/python3/cmk/base/plugins/agent_based/nextcloud_database.py @@ -34,7 +34,7 @@ def check_nextcloud_database(params, section): # create graph for database size yield Metric("nc_database_size", size) state = getStateLower(levels, opcache_hit_rate) - summary = f"Cache hit rate: {render.percent(opcache_hit_rate)}" + summary = f"PHP OPCache hit rate: {render.percent(opcache_hit_rate)}" details = f"\nDatabase type: {type}\nDatabase version: {version}\nDatabase size: {render.bytes(size)}" yield(Result(state=state, summary=summary, details=details)) diff --git a/local/share/check_mk/checkman/nextcloud_database b/local/share/check_mk/checkman/nextcloud_database index 08c598a..ad96286 100644 --- a/local/share/check_mk/checkman/nextcloud_database +++ b/local/share/check_mk/checkman/nextcloud_database @@ -4,13 +4,13 @@ catalog: unsorted license: GPL distribution: check_mk description: - Works with Nextcloud version 25.0.3 (use at your own risk with lower versions). + Works with Nextcloud version 25/26/27 (use at your own risk with lower versions). Tested only with mysql/mariab as underlying database. You may use a username/password or username/token combination to get access to the Nextcloud API. You can create this token within the personal settings of an administrative user in Nextcloud. Got to security settings and create a new app password, use this for the token. The user must not be secured with 2FA. Shows several information about a Nextcloud database (type/version/size). - The check will raise WARN/CRIT if Database OP cache hit rate is below the configurable levels. + The check will raise WARN/CRIT if Database PHP OPcache hit rate is below the configurable levels. inventory: one service is created (with several details) \ No newline at end of file diff --git a/local/share/check_mk/checkman/nextcloud_info b/local/share/check_mk/checkman/nextcloud_info index f14bd45..073d084 100644 --- a/local/share/check_mk/checkman/nextcloud_info +++ b/local/share/check_mk/checkman/nextcloud_info @@ -4,7 +4,7 @@ catalog: unsorted license: GPL distribution: check_mk description: - Works with Nextcloud version 25.0.3 (use at your own risk with lower versions). + Works with Nextcloud version 25/26/27 (use at your own risk with lower versions). Tested only with mysql/mariab as underlying database. You may use a username/password or username/token combination to get access to the Nextcloud API. You can create this token within the personal settings of an administrative user in Nextcloud. diff --git a/local/share/check_mk/checkman/nextcloud_users b/local/share/check_mk/checkman/nextcloud_users index db0a5e6..4345347 100644 --- a/local/share/check_mk/checkman/nextcloud_users +++ b/local/share/check_mk/checkman/nextcloud_users @@ -4,7 +4,7 @@ catalog: unsorted license: GPL distribution: check_mk description: - Works with Nextcloud version 25.0.3 (use at your own risk with lower versions). + Works with Nextcloud version 25/26/27 (use at your own risk with lower versions). You may use a username/password or username/token combination to get access to the Nextcloud API. You can create this token within the personal settings of an administrative user in Nextcloud. Got to security settings and create a new app password, use this for the token. diff --git a/local/share/check_mk/web/plugins/metrics/nextcloud_metrics.py b/local/share/check_mk/web/plugins/metrics/nextcloud_metrics.py index cbce1c3..d7cb0f9 100644 --- a/local/share/check_mk/web/plugins/metrics/nextcloud_metrics.py +++ b/local/share/check_mk/web/plugins/metrics/nextcloud_metrics.py @@ -96,7 +96,7 @@ metric_info["nc_database_size"] = { } metric_info["nc_database_opcache_hit_rate"] = { - "title": _("Database OP Cache Hit Rate"), + "title": _("Database PHP OPCache Hit Rate"), "unit": "%", "color": "24/a", } diff --git a/local/share/check_mk/web/plugins/wato/nextcloud_database_rules.py b/local/share/check_mk/web/plugins/wato/nextcloud_database_rules.py index 8881ca8..5d5c005 100644 --- a/local/share/check_mk/web/plugins/wato/nextcloud_database_rules.py +++ b/local/share/check_mk/web/plugins/wato/nextcloud_database_rules.py @@ -17,7 +17,7 @@ def _parameter_spec_nextcloud_database(): return Dictionary( elements=[ ("levels_database_opcache_hit_rate", Tuple( - title=_("Nextcloud levels for database opcache hit rate"), + title=_("Nextcloud levels for database php opcache hit rate"), elements=[ Percentage( title=_("Warning below"), diff --git a/local/share/check_mk/web/plugins/wato/nextcloud_params.py b/local/share/check_mk/web/plugins/wato/nextcloud_params.py index d425d37..32c524d 100644 --- a/local/share/check_mk/web/plugins/wato/nextcloud_params.py +++ b/local/share/check_mk/web/plugins/wato/nextcloud_params.py @@ -18,7 +18,6 @@ from cmk.gui.plugins.wato import ( ) from cmk.gui.plugins.wato.datasource_programs import RulespecGroupDatasourceProgramsCustom -#import cmk.gui.watolib as watolib def _valuespec_special_agent_nextcloud(): return Dictionary( @@ -53,7 +52,6 @@ def _valuespec_special_agent_nextcloud(): rulespec_registry.register( HostRulespec( - #factory_default=watolib.Rulespec.FACTORY_DEFAULT_UNUSED, group=RulespecGroupDatasourceProgramsCustom, name="special_agents:nextcloud", valuespec=_valuespec_special_agent_nextcloud, diff --git a/local/share/check_mk/web/plugins/wato/nextcloud_users_rules.py b/local/share/check_mk/web/plugins/wato/nextcloud_users_rules.py index 8440478..9eff766 100644 --- a/local/share/check_mk/web/plugins/wato/nextcloud_users_rules.py +++ b/local/share/check_mk/web/plugins/wato/nextcloud_users_rules.py @@ -11,6 +11,7 @@ from cmk.gui.valuespec import ( Tuple, Percentage, Integer, + TextAscii, Float, ) diff --git a/mkp/Nextcloud-2.3.3.mkp b/mkp/Nextcloud-2.3.3.mkp new file mode 100755 index 0000000000000000000000000000000000000000..55f7034b319ca6f7e4113dc965dfabf5246081ae GIT binary patch literal 10009 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 lWr_j0LT)8LysZ~1{