#!/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 pprint import pprint from cmk.utils import debug 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 debug.enabled(): pprint(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", )