#!/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 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_users(section) -> DiscoveryResult: for key in section: yield Service(item=key) def check_nextcloud_users(item, params, section) -> CheckResult: if debug.enabled(): pprint(section) 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", )