diff --git a/local/lib/python3/cmk/base/plugins/agent_based/mailcow_domains.py b/local/lib/python3/cmk/base/plugins/agent_based/mailcow_domains.py index 2a02743..f544ad5 100644 --- a/local/lib/python3/cmk/base/plugins/agent_based/mailcow_domains.py +++ b/local/lib/python3/cmk/base/plugins/agent_based/mailcow_domains.py @@ -42,8 +42,8 @@ def check_mailcow_domains(item, params, section): # create graph for used quota yield Metric("mailcow_domains_used_quota", percent_storage_used_for_messages, levels=levels) - summary_quota = f"Quota used is {render.percent(percent_storage_used_for_messages)}" - details_quota = f"Quota: {render.bytes(total_number_of_bytes_used)} of {render.bytes(quota)} used" + summary_quota = f"Storage quota used is {render.percent(percent_storage_used_for_messages)}" + details_quota = f"Storage quota: {render.bytes(total_number_of_bytes_used)} of {render.bytes(quota)} used" # create service yield(Result(state=state_quota, summary=summary_quota, details=details_quota)) @@ -112,19 +112,11 @@ def parse_mailcow_domains_section(string_table): create_time_data = "Not available" else: create_time_data = create_time_value - #create_time = int(create_time_value) - #curr_time = int(time.time()) - #diff_time = curr_time - create_time - #create_time_data = render.timespan(diff_time) modify_time_value = line[3] if modify_time_value == "None": modify_time_data = "Never" else: modify_time_data = modify_time_value - #modify_time = int(modify_time_value) - #curr_time = int(time.time()) - #diff_time = curr_time - modify_time - #modify_time_data = render.timespan(diff_time) # calculate percentage of used mailboxes max_number_of_mailboxes = int(line[4]) number_of_mailboxes = int(line[5]) diff --git a/local/lib/python3/cmk/base/plugins/agent_based/mailcow_mailboxes.py b/local/lib/python3/cmk/base/plugins/agent_based/mailcow_mailboxes.py new file mode 100644 index 0000000..8eebb78 --- /dev/null +++ b/local/lib/python3/cmk/base/plugins/agent_based/mailcow_mailboxes.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +import time +import random +from pprint import pprint +from .agent_based_api.v1 import get_value_store, get_rate, register, render, Service, Result, State, Metric + +def getStateUpper(levels, value): + warn, crit = levels + if value >= crit: + return State.CRIT + if value >= warn: + return State.WARN + return State.OK + +def discover_mailcow_mailboxes(section): + for key in section: + yield(Service(item = key)) + +def check_mailcow_mailboxes(item, params, section): + mailbox = item + # get all values from section + active = section[mailbox][0] + create_time = section[mailbox][1] + modify_time = section[mailbox][2] + display_name = section[mailbox][3] + number_of_messages = section[mailbox][4] + _percent_in_use = section[mailbox][5] + quota = section[mailbox][6] + total_number_of_bytes_used = section[mailbox][7] + percent_storage_used_for_messages = section[mailbox][8] + last_imap_login_data = section[mailbox][9] + last_pop3_login_data = section[mailbox][10] + last_smtp_login_data = section[mailbox][11] + + # create (main) service for used storage (mailbox quota) + warn, crit = params["levels_mailcow_mailboxes_quota_used"] + levels = (warn, crit) + state_quota = getStateUpper(levels, percent_storage_used_for_messages) + # create graph for used quota + yield Metric("mailcow_mailboxes_used_quota", percent_storage_used_for_messages, levels=levels) + summary_quota = f"Storage quota for mailbox of '{display_name}' is {render.percent(percent_storage_used_for_messages)}" + details_quota = f"Quota: {render.bytes(total_number_of_bytes_used)} of {render.bytes(quota)} used" + + # create service + yield(Result(state=state_quota, summary=summary_quota, details=details_quota)) + + # create some additional services and information only details + notice = f"Active: {active}" + yield(Result(state=State.OK, notice=notice)) + notice = f"Creation date: {create_time}" + yield(Result(state=State.OK, notice=notice)) + notice = f"Last modified: {modify_time}" + yield(Result(state=State.OK, notice=notice)) + + notice = f"Last IMAP login: {last_imap_login_data} ago" + yield(Result(state=State.OK, notice=notice)) + notice = f"Last POP3 login: {last_pop3_login_data} ago" + yield(Result(state=State.OK, notice=notice)) + notice = f"Last SMTP login: {last_smtp_login_data} ago" + yield(Result(state=State.OK, notice=notice)) + + # create service for number of messages + warn, crit = params["levels_mailcow_mailboxes_num_messages"] + levels = (warn, crit) + state_messages = getStateUpper(levels, number_of_messages) + yield Metric("mailcow_mailboxes_messages", number_of_messages, levels=levels) + notice = f"Number of messages: {number_of_messages}" + yield(Result(state=state_messages, notice=notice)) + + +def parse_mailcow_mailboxes_section(string_table): + # convert the raw output of the agent section into a meaningful structure, do type conversions and so on + parsed_data = {} + for line in string_table: + mailboxname = line[0] + value_active = int(line[1]) + if value_active == 1: + active = "yes" + else: + active = "no" + # calculate creation and last modification date in human readable format + create_time_value = line[2] + if create_time_value == "None": + create_time_data = "Not available" + else: + create_time_data = create_time_value + modify_time_value = line[3] + if modify_time_value == "None": + modify_time_data = "Never" + else: + modify_time_data = modify_time_value + # get display name + display_name = line[4] + # number of messages within mailbox + number_of_messages = int(line[5]) + # percent in use, rounded to full percent + percent_in_use = int(line[6]) + # calculate storage used for all messages in mailbox + quota = int(line[7]) + total_number_of_bytes_used = int(line[8]) + percent_storage_used_for_messages = total_number_of_bytes_used * 100 / quota + # get time of last login for IMAP/POP3/SMTP (seconds since epoch) + last_imap_login = int(line[9]) + last_pop3_login = int(line[10]) + last_smtp_login = int(line[11]) + # transfer these times into a human friendly format + if last_imap_login == 0: + last_imap_login_data = "Never" + else: + curr_time = int(time.time()) + diff_time = curr_time - last_imap_login + last_imap_login_data = render.timespan(diff_time) + if last_pop3_login == 0: + last_pop3_login_data = "Never" + else: + curr_time = int(time.time()) + diff_time = curr_time - last_pop3_login + last_pop3_login_data = render.timespan(diff_time) + if last_smtp_login == 0: + last_smtp_login_data = "Never" + else: + curr_time = int(time.time()) + diff_time = curr_time - last_smtp_login + last_smtp_login_data = render.timespan(diff_time) + # store all (calculated) data + parsed_data[f"{mailboxname}"] = [active, create_time_data, modify_time_data, + display_name, number_of_messages, percent_in_use, + quota, total_number_of_bytes_used, percent_storage_used_for_messages, + last_imap_login_data, last_pop3_login_data, last_smtp_login_data + ] + return parsed_data + +register.agent_section( + name = "mailcow_mailboxes", + parse_function = parse_mailcow_mailboxes_section, +) + +register.check_plugin( + name = "mailcow_mailboxes", + service_name = "Mailcow mailbox %s", + discovery_function = discover_mailcow_mailboxes, + check_function = check_mailcow_mailboxes, + check_default_parameters = { + "levels_mailcow_mailboxes_quota_used": (65.0, 85.0), + "levels_mailcow_mailboxes_num_messages": (1000, 2500), + }, + check_ruleset_name="mailcow_mailboxes", +) \ No newline at end of file diff --git a/local/share/check_mk/agents/special/agent_mailcow b/local/share/check_mk/agents/special/agent_mailcow index 7d1b7dc..f12d9d1 100755 --- a/local/share/check_mk/agents/special/agent_mailcow +++ b/local/share/check_mk/agents/special/agent_mailcow @@ -219,18 +219,18 @@ def getMailcowInfo(headers, verify, base_url): ''' Output is as follows: -mailbox name email address used for login -active 1 --> active, 0 --> not active -creation date "None" if ??? -last modified date "None" if never modified -name display name -number of messages -percent in use quota used, rounded to full percents -quota max quota in bytes -quota used quota used in bytes -last imap login seconds since epoch, 0 if never logged inin seconds since epoch -last pop3 login seconds since epoch, 0 if never logged in -last smtp login seconds since epoch, 0 if never logged in +0 mailbox name email address used for login +1 active 1 --> active, 0 --> not active +2 creation date "None" if ??? +3 last modified date "None" if never modified +4 name display name +5 number of messages +6 percent in use quota used, rounded to full percents +7 quota max quota in bytes +8 quota used quota used in bytes +9 last imap login seconds since epoch, 0 if never logged in +10 last pop3 login seconds since epoch, 0 if never logged in +11 last smtp login seconds since epoch, 0 if never logged in Example: user1@dom1.de;1;2022-04-29 14:29:34;2022-04-29 14:29:34;Sarah;2433;2;21474836480;495481374;1692520168;0;1692281537 @@ -266,17 +266,17 @@ def doCmkOutputMailcow(version, num_domains, num_mailboxes, num_global_messages) ''' Output is as follows: -domain_name -active 1 --> active, 0 --> not active -creation date "None" if ??? -last modified date "None" if never modified -max number mailboxes -number of mailboxes -max number of aliases -number of aliases -total number of messages -total number of bytes used in bytes -max quota in bytes +0 domain_name +1 active 1 --> active, 0 --> not active +2 creation date "None" if ??? +3 last modified date "None" if never modified +4 max number mailboxes +5 number of mailboxes +6 max number of aliases +7 number of aliases +8 total number of messages +9 total number of bytes used in bytes +10 max quota in bytes Example: dom1.de;1;2022-04-23 22:54:57;None;10;0;400;6;0;0;10737418240 diff --git a/local/share/check_mk/checkman/mailcow_mailboxes b/local/share/check_mk/checkman/mailcow_mailboxes new file mode 100644 index 0000000..232b32e --- /dev/null +++ b/local/share/check_mk/checkman/mailcow_mailboxes @@ -0,0 +1,18 @@ +title: Mailcow: Usage per Mailbox, Quota and Number of Messages +agents: linux +catalog: unsorted +license: GPL +distribution: check_mk +description: + Tested with Mailcow versions 2022-07a and higher (use at your own risk with lower versions). + Tested only with fully dockerized Mailcow instances. + You have to provide at least the hostname/IP of your Mailcow server and an API key. + Got to configuration settings and create a new API key (read-only access is sufficient). + Allow API access to at least your CheckMK server IP address. + Shows several information about a Mailcow mailbox, e.g. number of messages and quota. + The check will raise WARN/CRIT if quota usage is above the configurable levels. + The check will raise WARN/CRIT if number of messages is above the configurable levels. +item: + mailboxname +inventory: + one service is created for each mailbox \ No newline at end of file diff --git a/local/share/check_mk/web/plugins/metrics/mailcow_metrics.py b/local/share/check_mk/web/plugins/metrics/mailcow_metrics.py index 8e37082..5e87acf 100644 --- a/local/share/check_mk/web/plugins/metrics/mailcow_metrics.py +++ b/local/share/check_mk/web/plugins/metrics/mailcow_metrics.py @@ -57,4 +57,16 @@ metric_info["mailcow_domains_configured_mailboxes"] = { "title": _("Number of Configured Mailboxes"), "unit": "count", "color": "24/b", +} + +metric_info["mailcow_mailboxes_used_quota"] = { + "title": _("Mailbox Quota Used"), + "unit": "%", + "color": "24/a", +} + +metric_info["mailcow_mailboxes_messages"] = { + "title": _("Number of Messages"), + "unit": "count", + "color": "24/b", } \ No newline at end of file diff --git a/local/share/check_mk/web/plugins/perfometer/mailcow_perfometers.py b/local/share/check_mk/web/plugins/perfometer/mailcow_perfometers.py index 9a08574..b7bfea5 100644 --- a/local/share/check_mk/web/plugins/perfometer/mailcow_perfometers.py +++ b/local/share/check_mk/web/plugins/perfometer/mailcow_perfometers.py @@ -22,6 +22,17 @@ perfometer_info.append({ ], }) +perfometer_info.append({ + "type": "stacked", + "perfometers": [ + { + "type": "linear", + "segments": ["mailcow_mailboxes_used_quota"], + "total": 100.0, + }, + ], +}) + #perfometer_info.append({ # "type": "stacked", # "perfometers": [ diff --git a/local/share/check_mk/web/plugins/wato/mailcow_mailboxes_rules.py b/local/share/check_mk/web/plugins/wato/mailcow_mailboxes_rules.py new file mode 100644 index 0000000..9ea4a38 --- /dev/null +++ b/local/share/check_mk/web/plugins/wato/mailcow_mailboxes_rules.py @@ -0,0 +1,63 @@ +from cmk.gui.i18n import _ +from cmk.gui.plugins.wato import ( + CheckParameterRulespecWithItem, + rulespec_registry, + RulespecGroupCheckParametersApplications +) +from cmk.gui.valuespec import ( + Dictionary, + ListChoice, + TextAscii, + Percentage, + Tuple, + Float, + Integer +) + +def _item_spec_mailcow_mailboxes(): + return TextAscii( + title=_("Domain") + ) + +def _parameter_spec_mailcow_mailboxes(): + return Dictionary( + elements=[ + ("levels_mailcow_mailboxes_quota_used", Tuple( + title=_("Mailcow mailbox quota usage for storage"), + elements=[ + Percentage( + title=_("Warning at"), + default_value=65.0, + ), + Percentage( + title=_("Critical at"), + default_value=85.0, + ) + ], + )), + ("levels_mailcow_mailboxes_num_messages", Tuple( + title=_("Number of messages in mailbox"), + elements=[ + Integer( + title=_("Warning at"), + default_value=1000, + ), + Integer( + title=_("Critical at"), + default_value=2500, + ) + ], + )), + ], + ) + +rulespec_registry.register( + CheckParameterRulespecWithItem( + check_group_name="mailcow_mailboxes", + group=RulespecGroupCheckParametersApplications, + match_type="dict", + item_spec=_item_spec_mailcow_mailboxes, + parameter_valuespec=_parameter_spec_mailcow_mailboxes, + title=lambda: _("Levels for Mailcow mailboxes"), + ) +) \ No newline at end of file diff --git a/mkp/Mailcow-0.9.9.mkp b/mkp/Mailcow-0.9.9.mkp new file mode 100755 index 0000000..980f12c Binary files /dev/null and b/mkp/Mailcow-0.9.9.mkp differ