initial upload of version 3.1.1 which uses the new plugin API
This commit is contained in:
105
nextcloud/agent_based/nextcloud_database.py
Normal file
105
nextcloud/agent_based/nextcloud_database.py
Normal file
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
# pylint: disable=missing-module-docstring, unused-argument, missing-function-docstring
|
||||
# pylint: disable=line-too-long
|
||||
|
||||
from collections.abc import Mapping
|
||||
from typing import NotRequired, TypedDict
|
||||
|
||||
from cmk.agent_based.v2 import (
|
||||
AgentSection,
|
||||
CheckPlugin,
|
||||
CheckResult,
|
||||
Metric,
|
||||
render,
|
||||
Result,
|
||||
Service,
|
||||
State,
|
||||
StringTable,
|
||||
DiscoveryResult,
|
||||
)
|
||||
|
||||
|
||||
class _ItemData(TypedDict):
|
||||
dbtype: NotRequired[str]
|
||||
version: NotRequired[str]
|
||||
size: NotRequired[int]
|
||||
opcache_hit_rate: NotRequired[float]
|
||||
|
||||
|
||||
Section = Mapping[str, _ItemData]
|
||||
|
||||
|
||||
def get_state_lower(levels, value):
|
||||
warn, crit = levels
|
||||
if value < crit:
|
||||
return State.CRIT
|
||||
if value < warn:
|
||||
return State.WARN
|
||||
return State.OK
|
||||
|
||||
|
||||
def discover_nextcloud_database(section) -> DiscoveryResult:
|
||||
yield Service()
|
||||
|
||||
|
||||
def check_nextcloud_database(params, section) -> CheckResult:
|
||||
for key in section:
|
||||
if key == "database":
|
||||
opcache_hit_rate = section[key]["opcache_hit_rate"]
|
||||
size = section[key]["size"]
|
||||
dbtype = section[key]["dbtype"]
|
||||
version = section[key]["version"]
|
||||
_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
|
||||
)
|
||||
# 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
|
||||
summary = "PHP OPCache hit rate: 0% - please check if opcache_get_status is enabled"
|
||||
details = f"\nDatabase type: {dbtype}\nDatabase version: {version}\nDatabase size: {render.bytes(size)}"
|
||||
yield Result(state=state, summary=summary, details=details)
|
||||
|
||||
|
||||
def parse_nextcloud_database(string_table: StringTable) -> Section:
|
||||
parsed_data = {"database": {}}
|
||||
params_list = [
|
||||
"NC_Database_Type",
|
||||
"NC_Database_Version",
|
||||
"NC_Database_Size",
|
||||
"NC_OPCache_Hit_Rate",
|
||||
]
|
||||
for line in string_table:
|
||||
if line[0] in params_list:
|
||||
param = line[0]
|
||||
value = line[1]
|
||||
if param == "NC_Database_Type":
|
||||
parsed_data["database"]["dbtype"] = value
|
||||
elif param == "NC_Database_Version":
|
||||
parsed_data["database"]["version"] = value
|
||||
elif param == "NC_Database_Size":
|
||||
parsed_data["database"]["size"] = int(value)
|
||||
elif param == "NC_OPCache_Hit_Rate":
|
||||
parsed_data["database"]["opcache_hit_rate"] = float(value)
|
||||
return parsed_data
|
||||
|
||||
|
||||
agent_section_nextcloud_database = AgentSection(
|
||||
name="nextcloud_database",
|
||||
parse_function=parse_nextcloud_database,
|
||||
)
|
||||
|
||||
check_plugin_nextcloud_database = CheckPlugin(
|
||||
name="nextcloud_database",
|
||||
service_name="Nextcloud Database",
|
||||
discovery_function=discover_nextcloud_database,
|
||||
check_function=check_nextcloud_database,
|
||||
check_default_parameters={
|
||||
"levels_database_opcache_hit_rate": ("fixed", (95.0, 85.0)),
|
||||
},
|
||||
check_ruleset_name="nextcloud_database",
|
||||
)
|
||||
252
nextcloud/agent_based/nextcloud_info.py
Normal file
252
nextcloud/agent_based/nextcloud_info.py
Normal file
@@ -0,0 +1,252 @@
|
||||
#!/usr/bin/env python3
|
||||
# pylint: disable=missing-module-docstring, unused-argument, missing-function-docstring
|
||||
# pylint: disable=line-too-long, too-many-branches, too-many-locals, too-many-statements
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from cmk.agent_based.v2 import (
|
||||
AgentSection,
|
||||
CheckPlugin,
|
||||
CheckResult,
|
||||
Metric,
|
||||
render,
|
||||
Result,
|
||||
Service,
|
||||
State,
|
||||
StringTable,
|
||||
DiscoveryResult,
|
||||
)
|
||||
|
||||
|
||||
def get_state_upper(levels, value):
|
||||
warn, crit = levels
|
||||
if value >= crit:
|
||||
return State.CRIT
|
||||
if value >= warn:
|
||||
return State.WARN
|
||||
return State.OK
|
||||
|
||||
|
||||
def get_state_lower(levels, value):
|
||||
warn, crit = levels
|
||||
if value < crit:
|
||||
return State.CRIT
|
||||
if value < warn:
|
||||
return State.WARN
|
||||
return State.OK
|
||||
|
||||
|
||||
def discover_nextcloud_info(section) -> DiscoveryResult:
|
||||
yield Service()
|
||||
|
||||
|
||||
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"]
|
||||
# update infos are available only from Nextcloud version 28 onwards
|
||||
try:
|
||||
last_update = section[key]["last_update"]
|
||||
update_available = section[key]["update_available"]
|
||||
last_update_human = datetime.fromtimestamp(last_update)
|
||||
except KeyError:
|
||||
last_update = (
|
||||
"Update information not available, update to at least version 28"
|
||||
)
|
||||
update_available = "False"
|
||||
last_update_human = "Information not available"
|
||||
status = section[key]["status"]
|
||||
free_space = section[key]["freespace"]
|
||||
version = section[key]["version"]
|
||||
php_version = section[key]["php_version"]
|
||||
webserver = section[key]["webserver"]
|
||||
num_files = section[key]["number_files"]
|
||||
num_shares = section[key]["number_shares"]
|
||||
|
||||
# create graph for number of files and shares
|
||||
yield Metric("nc_num_files", num_files)
|
||||
yield Metric("nc_num_shares", num_shares)
|
||||
|
||||
# create overall result
|
||||
summary = f"Status is {status}, Last update check: {last_update_human}"
|
||||
details = f"Nextcloud version: {version}\nPHP version: {php_version}\nWebserver: {webserver}\n\nNumber of files: {num_files}\nNumber of shares: {num_shares}\n\nFree space on disk: {render.bytes(free_space)}\n"
|
||||
if status == "ok":
|
||||
state = State.OK
|
||||
else:
|
||||
state = State.CRIT
|
||||
yield Result(state=state, summary=summary, details=details)
|
||||
|
||||
# Create result for available updates
|
||||
if update_available != "False":
|
||||
state = State.WARN
|
||||
notice = "Update is available"
|
||||
else:
|
||||
state = State.OK
|
||||
notice = "No update available"
|
||||
if state != State.OK:
|
||||
yield Result(state=state, notice=notice)
|
||||
|
||||
# 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))
|
||||
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)
|
||||
notice = f"Number of files: {num_files}"
|
||||
if state != State.OK:
|
||||
yield Result(state=state, notice=notice)
|
||||
elif key == "users":
|
||||
num_users = section[key]["number"]
|
||||
num_active_last1hour = section[key]["active_last1hour"]
|
||||
num_active_last1day = section[key]["active_last1day"]
|
||||
num_active_last5min = section[key]["active_last5min"]
|
||||
# create graphs for number of users
|
||||
yield Metric("nc_num_users", num_users)
|
||||
yield Metric("nc_active_users_last_1hour", num_active_last1hour)
|
||||
yield Metric("nc_active_users_last_1day", num_active_last1day)
|
||||
yield Metric("nc_active_users_last_5min", num_active_last5min)
|
||||
notice = f"Number of users: {num_users}\n\nActive users last 5 min: {num_active_last5min}\nActive user since last hour: {num_active_last1hour}\nActive users since last day: {num_active_last1day}"
|
||||
yield Result(state=State.OK, notice=notice)
|
||||
elif key == "storages":
|
||||
num_storages = section[key]["number"]
|
||||
num_storages_home = section[key]["number_home"]
|
||||
num_storages_local = section[key]["number_local"]
|
||||
num_storages_other = section[key]["number_other"]
|
||||
# create graphs for number of storages
|
||||
yield Metric("nc_num_storages", num_storages)
|
||||
yield Metric("nc_num_storages_home", num_storages_home)
|
||||
yield Metric("nc_num_storages_local", num_storages_local)
|
||||
yield Metric("nc_num_storages_other", num_storages_other)
|
||||
notice = f"Number of storages: {num_storages}\nNumber of home/local/other storages: {num_storages_home}/{num_storages_local}/{num_storages_other}"
|
||||
yield Result(state=State.OK, notice=notice)
|
||||
elif key == "apps":
|
||||
# Workaround for Nextcloud 28, "apps" info is not always available
|
||||
try:
|
||||
num_apps_installed = section[key]["installed"]
|
||||
num_apps_with_updates_available = section[key]["with_updates_available"]
|
||||
if "app_versions" in section[key]:
|
||||
app_versions = section[key]["app_versions"]
|
||||
else:
|
||||
app_versions = ""
|
||||
# create graphs for number of apps
|
||||
_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 app_versions == "":
|
||||
notice = f"Number of installed apps: {num_apps_installed}\nNumber of apps with updates available: {num_apps_with_updates_available}"
|
||||
else:
|
||||
notice = f"Number of installed apps: {num_apps_installed}\nNumber of apps with updates available: {num_apps_with_updates_available}\nNew app versions available: {app_versions}"
|
||||
yield Result(state=state, notice=notice)
|
||||
except KeyError:
|
||||
# TBD
|
||||
pass
|
||||
|
||||
|
||||
def parse_nextcloud_info(string_table: StringTable) -> dict:
|
||||
parsed_data = {
|
||||
"nextcloud": {},
|
||||
"storages": {},
|
||||
"apps": {},
|
||||
"users": {},
|
||||
}
|
||||
params_list = [
|
||||
"NC_Version",
|
||||
"NC_Freespace",
|
||||
"NC_Status",
|
||||
"NC_Last_Update",
|
||||
"NC_Update_Available",
|
||||
"NC_Webserver",
|
||||
"NC_PHP_Version",
|
||||
"NC_Num_Users",
|
||||
"NC_Num_Files",
|
||||
"NC_Num_Shares",
|
||||
"NC_Num_Storages",
|
||||
"NC_Num_Storages_Home",
|
||||
"NC_Num_Storages_Local",
|
||||
"NC_Num_Storages_Other",
|
||||
"NC_Num_Apps_Installed",
|
||||
"NC_Num_Apps_Updates_Available",
|
||||
"NC_Apps_With_Updates_Available",
|
||||
"NC_Active_Users_Last_5Min",
|
||||
"NC_Active_Users_Last_1Hour",
|
||||
"NC_Active_Users_Last_1Day",
|
||||
]
|
||||
for line in string_table:
|
||||
if line[0] in params_list:
|
||||
param = line[0]
|
||||
value = line[1]
|
||||
if param == "NC_Version":
|
||||
parsed_data["nextcloud"]["version"] = value
|
||||
elif param == "NC_Freespace":
|
||||
parsed_data["nextcloud"]["freespace"] = float(value)
|
||||
elif param == "NC_Status":
|
||||
parsed_data["nextcloud"]["status"] = value
|
||||
elif param == "NC_Last_Update":
|
||||
parsed_data["nextcloud"]["last_update"] = int(value)
|
||||
elif param == "NC_Update_Available":
|
||||
parsed_data["nextcloud"]["update_available"] = value
|
||||
elif param == "NC_Webserver":
|
||||
parsed_data["nextcloud"]["webserver"] = value
|
||||
elif param == "NC_PHP_Version":
|
||||
parsed_data["nextcloud"]["php_version"] = value
|
||||
elif param == "NC_Num_Files":
|
||||
parsed_data["nextcloud"]["number_files"] = int(value)
|
||||
elif param == "NC_Num_Shares":
|
||||
parsed_data["nextcloud"]["number_shares"] = int(value)
|
||||
elif param == "NC_Num_Storages":
|
||||
parsed_data["storages"]["number"] = int(value)
|
||||
elif param == "NC_Num_Storages_Home":
|
||||
parsed_data["storages"]["number_home"] = int(value)
|
||||
elif param == "NC_Num_Storages_Local":
|
||||
parsed_data["storages"]["number_local"] = int(value)
|
||||
elif param == "NC_Num_Storages_Other":
|
||||
parsed_data["storages"]["number_other"] = int(value)
|
||||
elif param == "NC_Num_Apps_Installed":
|
||||
parsed_data["apps"]["installed"] = int(value)
|
||||
elif param == "NC_Num_Apps_Updates_Available":
|
||||
parsed_data["apps"]["with_updates_available"] = int(value)
|
||||
elif param == "NC_Apps_With_Updates_Available":
|
||||
parsed_data["apps"]["app_versions"] = value
|
||||
elif param == "NC_Num_Users":
|
||||
parsed_data["users"]["number"] = int(value)
|
||||
elif param == "NC_Active_Users_Last_5Min":
|
||||
parsed_data["users"]["active_last5min"] = int(value)
|
||||
elif param == "NC_Active_Users_Last_1Hour":
|
||||
parsed_data["users"]["active_last1hour"] = int(value)
|
||||
elif param == "NC_Active_Users_Last_1Day":
|
||||
parsed_data["users"]["active_last1day"] = int(value)
|
||||
return parsed_data
|
||||
|
||||
|
||||
agent_section_nextcloud_info = AgentSection(
|
||||
name="nextcloud_info",
|
||||
parse_function=parse_nextcloud_info,
|
||||
)
|
||||
|
||||
check_plugin_nextcloud_info = CheckPlugin(
|
||||
name="nextcloud_info",
|
||||
service_name="Nextcloud Info",
|
||||
discovery_function=discover_nextcloud_info,
|
||||
check_function=check_nextcloud_info,
|
||||
check_default_parameters={
|
||||
"levels_apps_with_updates_available": ("fixed", (1, 2)),
|
||||
"levels_free_space": ("fixed", (8.0, 4.0)),
|
||||
"levels_number_of_files": ("fixed", (100_000, 250_000)),
|
||||
},
|
||||
check_ruleset_name="nextcloud_info",
|
||||
)
|
||||
131
nextcloud/agent_based/nextcloud_users.py
Normal file
131
nextcloud/agent_based/nextcloud_users.py
Normal file
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env python3
|
||||
# pylint: disable=missing-module-docstring, unused-argument, missing-function-docstring
|
||||
# pylint: disable=line-too-long, too-many-locals
|
||||
|
||||
from time import time
|
||||
|
||||
from cmk.agent_based.v2 import (
|
||||
AgentSection,
|
||||
CheckPlugin,
|
||||
CheckResult,
|
||||
Metric,
|
||||
render,
|
||||
Result,
|
||||
Service,
|
||||
State,
|
||||
StringTable,
|
||||
DiscoveryResult,
|
||||
)
|
||||
|
||||
|
||||
def get_state_upper(levels, value):
|
||||
warn, crit = levels
|
||||
if value >= crit:
|
||||
return State.CRIT
|
||||
if value >= warn:
|
||||
return State.WARN
|
||||
return State.OK
|
||||
|
||||
|
||||
def get_state_lower(levels, value):
|
||||
warn, crit = levels
|
||||
if value < crit:
|
||||
return State.CRIT
|
||||
if value < warn:
|
||||
return State.WARN
|
||||
return State.OK
|
||||
|
||||
|
||||
def discover_nextcloud_users(section) -> DiscoveryResult:
|
||||
for key in section:
|
||||
yield Service(item=key)
|
||||
|
||||
|
||||
def check_nextcloud_users(item, params, section) -> CheckResult:
|
||||
userid = item
|
||||
quota_used_percent = section[item][0]
|
||||
quota_used_bytes = section[item][1]
|
||||
quota_total_bytes = section[item][2]
|
||||
display_name = section[item][3]
|
||||
last_login_human = section[item][4]
|
||||
last_login_since = section[item][5]
|
||||
free_space = quota_total_bytes - quota_used_bytes
|
||||
# print(free_space)
|
||||
_level_type, levels_quota_used = params["levels_users_quota_used"]
|
||||
_level_type, levels_free_space = params["levels_users_free_space"]
|
||||
if last_login_human == "never":
|
||||
quota_used_percent = 0
|
||||
details = f"User ID is '{userid}', Last login: {last_login_human}"
|
||||
summary = (
|
||||
f"Used quota of '{display_name}' can't be calculated yet (never logged in)"
|
||||
)
|
||||
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)
|
||||
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_quota_used", quota_used_percent, levels=levels_quota_used)
|
||||
state = get_state_upper(levels_quota_used, quota_used_percent)
|
||||
yield Result(state=state, summary=summary, details=details)
|
||||
|
||||
|
||||
def parse_nextcloud_users(string_table: StringTable) -> dict:
|
||||
# Raw output from check:
|
||||
# userid;displayname;lastLogin;quota_free;quota_quota;quota_relative;quota_total;quota_used
|
||||
# str;str;int(milli seconds since epoch);int(bytes);int(bytes);float(percent);int(bytes);int(bytes)
|
||||
parsed_data = {}
|
||||
for line in string_table:
|
||||
userid = line[0]
|
||||
display_name = line[1]
|
||||
last_login = int(line[2]) / 1000
|
||||
if last_login == 0:
|
||||
# user never logged in
|
||||
last_login_human = "never"
|
||||
last_login_since = "never"
|
||||
else:
|
||||
# user logged in at least once
|
||||
curr_time = int(time())
|
||||
login_diff = curr_time - last_login
|
||||
last_login_human = render.datetime(last_login)
|
||||
last_login_since = render.timespan(login_diff)
|
||||
quota_quota = int(line[4])
|
||||
if quota_quota == -3:
|
||||
# TBD, no quota set for user
|
||||
pass
|
||||
quota_relative = float(line[5])
|
||||
quota_total = float(line[6])
|
||||
quota_used = float(line[7])
|
||||
parsed_data[f"{userid}"] = [
|
||||
quota_relative,
|
||||
quota_used,
|
||||
quota_total,
|
||||
display_name,
|
||||
last_login_human,
|
||||
last_login_since,
|
||||
]
|
||||
return parsed_data
|
||||
|
||||
|
||||
agent_section_nextcloud_users = AgentSection(
|
||||
name="nextcloud_users",
|
||||
parse_function=parse_nextcloud_users,
|
||||
)
|
||||
|
||||
check_plugin_nextcloud_users = CheckPlugin(
|
||||
name="nextcloud_users",
|
||||
service_name="Nextcloud User %s",
|
||||
discovery_function=discover_nextcloud_users,
|
||||
check_function=check_nextcloud_users,
|
||||
check_default_parameters={
|
||||
"levels_users_quota_used": ("fixed", (65.0, 85.0)),
|
||||
"levels_users_free_space": ("fixed", (256.0, 128.0)),
|
||||
},
|
||||
check_ruleset_name="nextcloud_users",
|
||||
)
|
||||
Reference in New Issue
Block a user