initial upload of version 2.1.0 which uses the new plugin API
This commit is contained in:
parent
358f84307c
commit
cc2aaee908
23
README.md
23
README.md
@ -12,22 +12,21 @@ Mailboxes with quota usage, number of messages, last logins via IMAP/POP3/SMTP
|
|||||||
## Caveats:
|
## Caveats:
|
||||||
Tested only with dockerized versions of Mailcow
|
Tested only with dockerized versions of Mailcow
|
||||||
|
|
||||||
Tested with Mailcow version 2022-07a and higher
|
Tested with Mailcow version 2023-01 and higher
|
||||||
|
|
||||||
Please feel free to add other working environments via review/email.
|
Please feel free to add other working environments via review/email.
|
||||||
|
|
||||||
## Upgrade from older MKPs (before 1.2.0):
|
Upgrade from older MKPs (before 2.1.0): If you upgrade from a already installed version before 2.1.0, you have to re-create your rules for the "Mailcow Server Information" (reason: parameter handling changes and migration to the new plugin API).
|
||||||
If you upgrade from a already installed version before 1.2.0, you have to re-create your rules for the "Mailcow Server Information" (reason: massive parameter changes).
|
HINT: It is a good idea to take a screenshot from all other Mailcow related rules as well.
|
||||||
|
|
||||||
## Steps to accomplish this without problems:
|
Steps to accomplish this without problems:
|
||||||
|
|
||||||
1. Take a screenshot of your settings in the above mentioned ruleset
|
|
||||||
2. Assure that you have access to the API keys you used within the current rules
|
|
||||||
3. Delete all rules for "Mailcow Server Information"
|
|
||||||
4. Install and enable the new MKP
|
|
||||||
5. Re-create your rules with the previously saved information from steps 1 and 2
|
|
||||||
6. Apply your changes
|
|
||||||
|
|
||||||
|
Take a screenshot of your settings in the above mentioned ruleset
|
||||||
|
Assure that you have access to the API keys you used within the current rules
|
||||||
|
Delete all rules for "Mailcow Server Information"
|
||||||
|
Install and enable the new MKP
|
||||||
|
Re-create your rules with the previously saved information from steps 1 and 2
|
||||||
|
Apply your changes
|
||||||
|
|
||||||
## General installation instructions:
|
## General installation instructions:
|
||||||
|
|
||||||
@ -57,6 +56,8 @@ If you upgrade from a already installed version before 1.2.0, you have to re-cre
|
|||||||
|
|
||||||
## Version history:
|
## Version history:
|
||||||
|
|
||||||
|
2025/03/30 2.1.0 Migration to new plugin API done
|
||||||
|
|
||||||
2024/01/26 1.2.0 Added password store option for the API key, added version check
|
2024/01/26 1.2.0 Added password store option for the API key, added version check
|
||||||
|
|
||||||
2023/09/22: 1.1.4 Bugfix for the last bugfix :-)
|
2023/09/22: 1.1.4 Bugfix for the last bugfix :-)
|
||||||
|
@ -1,162 +0,0 @@
|
|||||||
#!/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
|
|
||||||
|
|
||||||
# services with item --> storageid and usage of value_store (to be able to calculate rates)
|
|
||||||
def discover_mailcow_domains(section):
|
|
||||||
for key in section:
|
|
||||||
yield(Service(item = key))
|
|
||||||
|
|
||||||
def check_mailcow_domains(item, params, section):
|
|
||||||
domain = item
|
|
||||||
# get all values from section
|
|
||||||
active = section[domain][0]
|
|
||||||
create_time = section[domain][1]
|
|
||||||
modify_time = section[domain][2]
|
|
||||||
max_number_of_mailboxes = section[domain][3]
|
|
||||||
number_of_mailboxes = section[domain][4]
|
|
||||||
percent_used_mailboxes = section[domain][5]
|
|
||||||
max_number_of_aliases = section[domain][6]
|
|
||||||
number_of_aliases = section[domain][7]
|
|
||||||
percent_used_aliases = section[domain][8]
|
|
||||||
total_number_of_messages = section[domain][9]
|
|
||||||
total_number_of_bytes_used = section[domain][10]
|
|
||||||
quota = section[domain][11]
|
|
||||||
percent_storage_used_for_messages = section[domain][12]
|
|
||||||
|
|
||||||
# create (main) service for used storage (domain quota)
|
|
||||||
warn, crit = params["levels_mailcow_domains_quota_used"]
|
|
||||||
levels = (warn, crit)
|
|
||||||
state_quota = getStateUpper(levels, percent_storage_used_for_messages)
|
|
||||||
|
|
||||||
# create graph for used quota
|
|
||||||
yield Metric("mailcow_domains_used_quota", percent_storage_used_for_messages, levels=levels)
|
|
||||||
|
|
||||||
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))
|
|
||||||
|
|
||||||
# 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))
|
|
||||||
|
|
||||||
# create service for number of configured mailboxes (percent)
|
|
||||||
warn, crit = params["levels_mailcow_domains_mailboxes_used"]
|
|
||||||
levels = (warn, crit)
|
|
||||||
state_mailboxes = getStateUpper(levels, percent_used_mailboxes)
|
|
||||||
yield Metric("mailcow_domains_mailboxes", percent_used_mailboxes, levels=levels)
|
|
||||||
notice = f"Used mailboxes: {render.percent(percent_used_mailboxes)}, {number_of_mailboxes} of {max_number_of_mailboxes} in use"
|
|
||||||
yield(Result(state=state_mailboxes, notice=notice))
|
|
||||||
|
|
||||||
# create service for number of configured aliases (percent)
|
|
||||||
warn, crit = params["levels_mailcow_domains_aliases_used"]
|
|
||||||
levels = (warn, crit)
|
|
||||||
state_aliases = getStateUpper(levels, percent_used_aliases)
|
|
||||||
yield Metric("mailcow_domains_aliases", percent_used_aliases, levels=levels)
|
|
||||||
notice = f"Used aliases: {render.percent(percent_used_aliases)}, {number_of_aliases} of {max_number_of_aliases} in use"
|
|
||||||
yield(Result(state=state_aliases, notice=notice))
|
|
||||||
|
|
||||||
# create service for number of messages
|
|
||||||
warn, crit = params["levels_mailcow_domains_num_messages"]
|
|
||||||
levels = (warn, crit)
|
|
||||||
state_messages = getStateUpper(levels, total_number_of_messages)
|
|
||||||
yield Metric("mailcow_domains_messages", total_number_of_messages, levels=levels)
|
|
||||||
notice = f"Number of messages: {total_number_of_messages}"
|
|
||||||
yield(Result(state=state_messages, notice=notice))
|
|
||||||
|
|
||||||
# create service for number of configured aliases (absolute)
|
|
||||||
warn, crit = params["levels_mailcow_domains_num_aliases"]
|
|
||||||
levels = (warn, crit)
|
|
||||||
state_aliases = getStateUpper(levels, number_of_aliases)
|
|
||||||
yield Metric("mailcow_domains_configured_aliases", number_of_aliases, levels=levels)
|
|
||||||
notice = f"Number of aliases: {number_of_aliases}, max {max_number_of_aliases} allowed"
|
|
||||||
yield(Result(state=state_aliases, notice=notice))
|
|
||||||
|
|
||||||
# create service for number of configured mailboxes (absolute)
|
|
||||||
warn, crit = params["levels_mailcow_domains_num_mailboxes"]
|
|
||||||
levels = (warn, crit)
|
|
||||||
state_mailboxes = getStateUpper(levels, number_of_mailboxes)
|
|
||||||
yield Metric("mailcow_domains_configured_mailboxes", number_of_mailboxes, levels=levels)
|
|
||||||
notice = f"Number of mailboxes: {number_of_mailboxes}, max {max_number_of_mailboxes} allowed"
|
|
||||||
yield(Result(state=state_mailboxes, notice=notice))
|
|
||||||
|
|
||||||
def parse_mailcow_domains_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:
|
|
||||||
domainname = 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
|
|
||||||
# calculate percentage of used mailboxes
|
|
||||||
max_number_of_mailboxes = int(line[4])
|
|
||||||
number_of_mailboxes = int(line[5])
|
|
||||||
percent_used_mailboxes = number_of_mailboxes * 100 / max_number_of_mailboxes
|
|
||||||
# calculate percentage of used aliases
|
|
||||||
max_number_of_aliases = int(line[6])
|
|
||||||
number_of_aliases = int(line[7])
|
|
||||||
percent_used_aliases = number_of_aliases * 100 / max_number_of_aliases
|
|
||||||
# number of messages within domain
|
|
||||||
total_number_of_messages = int(line[8])
|
|
||||||
# calculate storage used for all messages in domain
|
|
||||||
total_number_of_bytes_used = int(line[9])
|
|
||||||
quota = int(line[10])
|
|
||||||
percent_storage_used_for_messages = total_number_of_bytes_used * 100 / quota
|
|
||||||
# store all (calculated) data
|
|
||||||
parsed_data[f"{domainname}"] = [active, create_time_data, modify_time_data,
|
|
||||||
max_number_of_mailboxes, number_of_mailboxes, percent_used_mailboxes,
|
|
||||||
max_number_of_aliases, number_of_aliases, percent_used_aliases,
|
|
||||||
total_number_of_messages,
|
|
||||||
total_number_of_bytes_used, quota, percent_storage_used_for_messages
|
|
||||||
]
|
|
||||||
return parsed_data
|
|
||||||
|
|
||||||
register.agent_section(
|
|
||||||
name = "mailcow_domains",
|
|
||||||
parse_function = parse_mailcow_domains_section,
|
|
||||||
)
|
|
||||||
|
|
||||||
register.check_plugin(
|
|
||||||
name = "mailcow_domains",
|
|
||||||
service_name = "Mailcow domain %s",
|
|
||||||
discovery_function = discover_mailcow_domains,
|
|
||||||
check_function = check_mailcow_domains,
|
|
||||||
check_default_parameters = {
|
|
||||||
"levels_mailcow_domains_quota_used": (65.0, 85.0),
|
|
||||||
"levels_mailcow_domains_mailboxes_used": (65.0, 85.0),
|
|
||||||
"levels_mailcow_domains_aliases_used": (65.0, 85.0),
|
|
||||||
"levels_mailcow_domains_num_messages": (10000, 25000),
|
|
||||||
"levels_mailcow_domains_num_aliases": (100, 250),
|
|
||||||
"levels_mailcow_domains_num_mailboxes": (100, 250),
|
|
||||||
},
|
|
||||||
check_ruleset_name="mailcow_domains",
|
|
||||||
)
|
|
@ -1,142 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
from pprint import pprint
|
|
||||||
from .agent_based_api.v1 import 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 getStateLower(levels, value):
|
|
||||||
warn, crit = levels
|
|
||||||
if value < crit:
|
|
||||||
return State.CRIT
|
|
||||||
if value < warn:
|
|
||||||
return State.WARN
|
|
||||||
return State.OK
|
|
||||||
|
|
||||||
|
|
||||||
def discover_mailcow_info(section):
|
|
||||||
yield (Service())
|
|
||||||
|
|
||||||
|
|
||||||
def check_mailcow_info(params, section):
|
|
||||||
for key in section:
|
|
||||||
if key == "mailcow":
|
|
||||||
# get thresholds
|
|
||||||
levels_num_domains = params["levels_num_domains"]
|
|
||||||
levels_num_mailboxes = params["levels_num_mailboxes"]
|
|
||||||
levels_num_global_messages = params["levels_num_global_messages"]
|
|
||||||
version = section[key]["version"]
|
|
||||||
git_version = section[key]["git_version"]
|
|
||||||
check_version_enabled = section[key]["check_version_enabled"]
|
|
||||||
update_available = section[key]["update_available"]
|
|
||||||
num_domains = section[key]["num_domains"]
|
|
||||||
num_mailboxes = section[key]["num_mailboxes"]
|
|
||||||
num_global_messages = section[key]["num_global_messages"]
|
|
||||||
|
|
||||||
# create graphs for number of domains, mailboxes and messages
|
|
||||||
yield (Metric("mc_num_domains", num_domains, levels=levels_num_domains))
|
|
||||||
yield (
|
|
||||||
Metric("mc_num_mailboxes", num_mailboxes, levels=levels_num_mailboxes)
|
|
||||||
)
|
|
||||||
yield (
|
|
||||||
Metric(
|
|
||||||
"mc_num_global_messages",
|
|
||||||
num_global_messages,
|
|
||||||
levels=levels_num_global_messages,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# create overall result
|
|
||||||
if check_version_enabled:
|
|
||||||
if update_available:
|
|
||||||
summary = f"Update available: Running version is {version}, Github version is: {git_version}"
|
|
||||||
state = State.WARN
|
|
||||||
else:
|
|
||||||
summary = f"No update available: Running version is {version}, Github version is: {git_version}"
|
|
||||||
state = State.OK
|
|
||||||
else:
|
|
||||||
summary = f"Version is {version}, Update check is disabled"
|
|
||||||
state = State.OK
|
|
||||||
details = f"Mailcow version: {version}\nNumber of domains: {num_domains}\nNumber of mailboxes: {num_mailboxes}\nNumber of messages: {num_global_messages}"
|
|
||||||
yield Result(state=state, summary=summary, details=details)
|
|
||||||
|
|
||||||
# Create result for number of domains
|
|
||||||
warn, crit = levels_num_domains
|
|
||||||
state = getStateUpper((warn, crit), num_domains)
|
|
||||||
notice = f"Number of domains: {num_domains}"
|
|
||||||
if state != State.OK:
|
|
||||||
yield (Result(state=state, notice=notice))
|
|
||||||
|
|
||||||
# Create result for number of mailboxes
|
|
||||||
warn, crit = levels_num_mailboxes
|
|
||||||
state = getStateUpper((warn, crit), num_mailboxes)
|
|
||||||
notice = f"Number of mailboxes: {num_mailboxes}"
|
|
||||||
if state != State.OK:
|
|
||||||
yield (Result(state=state, notice=notice))
|
|
||||||
|
|
||||||
# Create result for number of global messages
|
|
||||||
warn, crit = levels_num_global_messages
|
|
||||||
state = getStateUpper((warn, crit), num_global_messages)
|
|
||||||
notice = f"Number of messages: {num_global_messages}"
|
|
||||||
if state != State.OK:
|
|
||||||
yield (Result(state=state, notice=notice))
|
|
||||||
|
|
||||||
|
|
||||||
def parse_mailcow_info_section(string_table):
|
|
||||||
# pprint(string_table)
|
|
||||||
parsed_data = {
|
|
||||||
"mailcow": {},
|
|
||||||
}
|
|
||||||
# we expect only one line
|
|
||||||
line = string_table[0]
|
|
||||||
version = line[0]
|
|
||||||
num_domains = int(line[1])
|
|
||||||
num_mailboxes = int(line[2])
|
|
||||||
num_global_messages = int(line[3])
|
|
||||||
git_version = line[4]
|
|
||||||
update_available = line[5]
|
|
||||||
if update_available == "True":
|
|
||||||
update_available = True
|
|
||||||
else:
|
|
||||||
update_available = False
|
|
||||||
check_version_enabled = line[6]
|
|
||||||
if check_version_enabled == "True":
|
|
||||||
check_version_enabled = True
|
|
||||||
else:
|
|
||||||
check_version_enabled = False
|
|
||||||
parsed_data["mailcow"]["version"] = version
|
|
||||||
parsed_data["mailcow"]["num_domains"] = num_domains
|
|
||||||
parsed_data["mailcow"]["num_mailboxes"] = num_mailboxes
|
|
||||||
parsed_data["mailcow"]["num_global_messages"] = num_global_messages
|
|
||||||
parsed_data["mailcow"]["git_version"] = git_version
|
|
||||||
parsed_data["mailcow"]["update_available"] = update_available
|
|
||||||
parsed_data["mailcow"]["check_version_enabled"] = check_version_enabled
|
|
||||||
# pprint(parsed_data)
|
|
||||||
return parsed_data
|
|
||||||
|
|
||||||
|
|
||||||
register.agent_section(
|
|
||||||
name="mailcow_info",
|
|
||||||
parse_function=parse_mailcow_info_section,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
register.check_plugin(
|
|
||||||
name="mailcow_info",
|
|
||||||
service_name="Mailcow Info",
|
|
||||||
discovery_function=discover_mailcow_info,
|
|
||||||
check_function=check_mailcow_info,
|
|
||||||
check_default_parameters={
|
|
||||||
"levels_num_domains": (100, 200),
|
|
||||||
"levels_num_mailboxes": (500, 1000),
|
|
||||||
"levels_num_global_messages": (100000, 250000),
|
|
||||||
},
|
|
||||||
check_ruleset_name="mailcow_info",
|
|
||||||
)
|
|
@ -1,155 +0,0 @@
|
|||||||
#!/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])
|
|
||||||
# calculate storage used for all messages in mailbox
|
|
||||||
quota = int(line[7])
|
|
||||||
total_number_of_bytes_used = int(line[8])
|
|
||||||
if quota == 0:
|
|
||||||
# quota is not set, if this is the case, line[6] contains no numeric value, but the char "-"
|
|
||||||
# so set all usage counters to zero
|
|
||||||
percent_in_use = 0
|
|
||||||
percent_storage_used_for_messages = 0
|
|
||||||
else:
|
|
||||||
# percent in use, rounded to full percent (calculated by Mailcow)
|
|
||||||
percent_in_use = int(line[6])
|
|
||||||
# let's calculate our own value
|
|
||||||
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",
|
|
||||||
)
|
|
@ -1,19 +0,0 @@
|
|||||||
def agent_mailcow_arguments(params, hostname, ipaddress):
|
|
||||||
return [
|
|
||||||
"--hostname",
|
|
||||||
params["hostname"],
|
|
||||||
"--apikey",
|
|
||||||
passwordstore_get_cmdline("%s", params["apikey"]),
|
|
||||||
"--port",
|
|
||||||
params["port"],
|
|
||||||
"--check-version",
|
|
||||||
params["check_version"],
|
|
||||||
"--no-https",
|
|
||||||
params["no_https"],
|
|
||||||
"--no-cert-check",
|
|
||||||
params["no_cert_check"],
|
|
||||||
ipaddress,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
special_agent_info["mailcow"] = agent_mailcow_arguments
|
|
@ -1,72 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
from cmk.gui.i18n import _
|
|
||||||
from cmk.gui.plugins.metrics import (
|
|
||||||
metric_info,
|
|
||||||
graph_info,
|
|
||||||
)
|
|
||||||
|
|
||||||
metric_info["mc_num_domains"] = {
|
|
||||||
"title": _("Number of Domains"),
|
|
||||||
"unit": "count",
|
|
||||||
"color": "44/a",
|
|
||||||
}
|
|
||||||
|
|
||||||
metric_info["mc_num_mailboxes"] = {
|
|
||||||
"title": _("Number of Mailboxes"),
|
|
||||||
"unit": "count",
|
|
||||||
"color": "44/b",
|
|
||||||
}
|
|
||||||
|
|
||||||
metric_info["mc_num_global_messages"] = {
|
|
||||||
"title": _("Number of Messages"),
|
|
||||||
"unit": "count",
|
|
||||||
"color": "42/a",
|
|
||||||
}
|
|
||||||
|
|
||||||
metric_info["mailcow_domains_used_quota"] = {
|
|
||||||
"title": _("Domain Quota Used"),
|
|
||||||
"unit": "%",
|
|
||||||
"color": "24/a",
|
|
||||||
}
|
|
||||||
|
|
||||||
metric_info["mailcow_domains_mailboxes"] = {
|
|
||||||
"title": _("Domain Mailboxes Quota Used"),
|
|
||||||
"unit": "%",
|
|
||||||
"color": "44/b",
|
|
||||||
}
|
|
||||||
|
|
||||||
metric_info["mailcow_domains_aliases"] = {
|
|
||||||
"title": _("Domain Aliases Quota Used"),
|
|
||||||
"unit": "%",
|
|
||||||
"color": "44/a",
|
|
||||||
}
|
|
||||||
|
|
||||||
metric_info["mailcow_domains_messages"] = {
|
|
||||||
"title": _("Global Number of Messages"),
|
|
||||||
"unit": "count",
|
|
||||||
"color": "24/a",
|
|
||||||
}
|
|
||||||
|
|
||||||
metric_info["mailcow_domains_configured_aliases"] = {
|
|
||||||
"title": _("Number of Configured Aliases"),
|
|
||||||
"unit": "count",
|
|
||||||
"color": "24/a",
|
|
||||||
}
|
|
||||||
|
|
||||||
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",
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
from cmk.gui.plugins.metrics import perfometer_info
|
|
||||||
|
|
||||||
perfometer_info.append(
|
|
||||||
{
|
|
||||||
"type": "stacked",
|
|
||||||
"perfometers": [
|
|
||||||
{
|
|
||||||
"type": "linear",
|
|
||||||
"segments": [
|
|
||||||
"mc_num_domains",
|
|
||||||
"mc_num_mailboxes",
|
|
||||||
"mc_num_global_messages",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
perfometer_info.append(
|
|
||||||
{
|
|
||||||
"type": "stacked",
|
|
||||||
"perfometers": [
|
|
||||||
{
|
|
||||||
"type": "linear",
|
|
||||||
"segments": ["mailcow_domains_used_quota"],
|
|
||||||
"total": 100.0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
perfometer_info.append(
|
|
||||||
{
|
|
||||||
"type": "stacked",
|
|
||||||
"perfometers": [
|
|
||||||
{
|
|
||||||
"type": "linear",
|
|
||||||
"segments": ["mailcow_mailboxes_used_quota"],
|
|
||||||
"total": 100.0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
)
|
|
@ -1,115 +0,0 @@
|
|||||||
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_domains():
|
|
||||||
return TextAscii(
|
|
||||||
title=_("Domain name")
|
|
||||||
)
|
|
||||||
|
|
||||||
def _parameter_spec_mailcow_domains():
|
|
||||||
return Dictionary(
|
|
||||||
elements=[
|
|
||||||
("levels_mailcow_domains_quota_used", Tuple(
|
|
||||||
title=_("Mailcow domains quota usage for storage"),
|
|
||||||
elements=[
|
|
||||||
Percentage(
|
|
||||||
title=_("Warning at"),
|
|
||||||
default_value=65.0,
|
|
||||||
),
|
|
||||||
Percentage(
|
|
||||||
title=_("Critical at"),
|
|
||||||
default_value=85.0,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
("levels_mailcow_domains_mailboxes_used", Tuple(
|
|
||||||
title=_("Mailcow domains mailboxes usage"),
|
|
||||||
elements=[
|
|
||||||
Percentage(
|
|
||||||
title=_("Warning at"),
|
|
||||||
default_value=65.0,
|
|
||||||
),
|
|
||||||
Percentage(
|
|
||||||
title=_("Critical at"),
|
|
||||||
default_value=85.0,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
("levels_mailcow_domains_aliases_used", Tuple(
|
|
||||||
title=_("Mailcow domains aliases usage"),
|
|
||||||
elements=[
|
|
||||||
Percentage(
|
|
||||||
title=_("Warning at"),
|
|
||||||
default_value=65.0,
|
|
||||||
),
|
|
||||||
Percentage(
|
|
||||||
title=_("Critical at"),
|
|
||||||
default_value=85.0,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
("levels_mailcow_domains_num_messages", Tuple(
|
|
||||||
title=_("Number of messages"),
|
|
||||||
elements=[
|
|
||||||
Integer(
|
|
||||||
title=_("Warning at"),
|
|
||||||
default_value=10000,
|
|
||||||
),
|
|
||||||
Integer(
|
|
||||||
title=_("Critical at"),
|
|
||||||
default_value=25000,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
("levels_mailcow_domains_num_aliases", Tuple(
|
|
||||||
title=_("Number of configured aliases"),
|
|
||||||
elements=[
|
|
||||||
Integer(
|
|
||||||
title=_("Warning at"),
|
|
||||||
default_value=100,
|
|
||||||
),
|
|
||||||
Integer(
|
|
||||||
title=_("Critical at"),
|
|
||||||
default_value=250,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
("levels_mailcow_domains_num_mailboxes", Tuple(
|
|
||||||
title=_("Number of configured mailboxes"),
|
|
||||||
elements=[
|
|
||||||
Integer(
|
|
||||||
title=_("Warning at"),
|
|
||||||
default_value=100,
|
|
||||||
),
|
|
||||||
Integer(
|
|
||||||
title=_("Critical at"),
|
|
||||||
default_value=250,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
rulespec_registry.register(
|
|
||||||
CheckParameterRulespecWithItem(
|
|
||||||
check_group_name="mailcow_domains",
|
|
||||||
group=RulespecGroupCheckParametersApplications,
|
|
||||||
match_type="dict",
|
|
||||||
item_spec=_item_spec_mailcow_domains,
|
|
||||||
parameter_valuespec=_parameter_spec_mailcow_domains,
|
|
||||||
title=lambda: _("Levels for Mailcow domains"),
|
|
||||||
)
|
|
||||||
)
|
|
@ -1,87 +0,0 @@
|
|||||||
from cmk.gui.i18n import _
|
|
||||||
from cmk.gui.plugins.wato import (
|
|
||||||
CheckParameterRulespecWithoutItem,
|
|
||||||
rulespec_registry,
|
|
||||||
RulespecGroupCheckParametersApplications,
|
|
||||||
)
|
|
||||||
|
|
||||||
from cmk.gui.valuespec import (
|
|
||||||
Dictionary,
|
|
||||||
ListChoice,
|
|
||||||
Tuple,
|
|
||||||
Percentage,
|
|
||||||
Integer,
|
|
||||||
Float,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _parameter_spec_mailcow_info():
|
|
||||||
return Dictionary(
|
|
||||||
elements=[
|
|
||||||
(
|
|
||||||
"levels_num_domains",
|
|
||||||
Tuple(
|
|
||||||
title=_("Number of email domains"),
|
|
||||||
elements=[
|
|
||||||
Integer(
|
|
||||||
title=_("Warning at"),
|
|
||||||
size=32,
|
|
||||||
default_value=100,
|
|
||||||
),
|
|
||||||
Integer(
|
|
||||||
title=_("Critical at"),
|
|
||||||
size=32,
|
|
||||||
default_value=200,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"levels_num_mailboxes",
|
|
||||||
Tuple(
|
|
||||||
title=_("Number of mailboxes"),
|
|
||||||
elements=[
|
|
||||||
Integer(
|
|
||||||
title=_("Warning at"),
|
|
||||||
size=32,
|
|
||||||
default_value=500,
|
|
||||||
),
|
|
||||||
Integer(
|
|
||||||
title=_("Critical at"),
|
|
||||||
size=32,
|
|
||||||
default_value=1000,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"levels_num_global_messages",
|
|
||||||
Tuple(
|
|
||||||
title=_("Number of messages"),
|
|
||||||
elements=[
|
|
||||||
Integer(
|
|
||||||
title=_("Warning at"),
|
|
||||||
size=32,
|
|
||||||
default_value=100000,
|
|
||||||
),
|
|
||||||
Integer(
|
|
||||||
title=_("Critical at"),
|
|
||||||
size=32,
|
|
||||||
default_value=250000,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
rulespec_registry.register(
|
|
||||||
CheckParameterRulespecWithoutItem(
|
|
||||||
check_group_name="mailcow_info",
|
|
||||||
group=RulespecGroupCheckParametersApplications,
|
|
||||||
match_type="dict",
|
|
||||||
parameter_valuespec=_parameter_spec_mailcow_info,
|
|
||||||
title=lambda: _("Levels for Mailcow info"),
|
|
||||||
)
|
|
||||||
)
|
|
@ -1,65 +0,0 @@
|
|||||||
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=_("Mailbox name")
|
|
||||||
)
|
|
||||||
|
|
||||||
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"),
|
|
||||||
size=32,
|
|
||||||
default_value=1000,
|
|
||||||
),
|
|
||||||
Integer(
|
|
||||||
title=_("Critical at"),
|
|
||||||
size=32,
|
|
||||||
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"),
|
|
||||||
)
|
|
||||||
)
|
|
@ -1,98 +0,0 @@
|
|||||||
from cmk.gui.i18n import _
|
|
||||||
|
|
||||||
from cmk.gui.plugins.wato.special_agents.common import (
|
|
||||||
RulespecGroupDatasourceProgramsApps,
|
|
||||||
RulespecGroupDatasourceProgramsCustom,
|
|
||||||
RulespecGroupDatasourceProgramsHardware,
|
|
||||||
RulespecGroupDatasourceProgramsOS,
|
|
||||||
RulespecGroupDatasourceProgramsTesting,
|
|
||||||
)
|
|
||||||
|
|
||||||
from cmk.gui.plugins.wato.utils import (
|
|
||||||
IndividualOrStoredPassword,
|
|
||||||
rulespec_registry,
|
|
||||||
CheckParameterRulespecWithItem,
|
|
||||||
CheckParameterRulespecWithoutItem,
|
|
||||||
HostRulespec,
|
|
||||||
Rulespec,
|
|
||||||
)
|
|
||||||
|
|
||||||
from cmk.gui.valuespec import (
|
|
||||||
Dictionary,
|
|
||||||
ListChoice,
|
|
||||||
Checkbox,
|
|
||||||
TextAscii,
|
|
||||||
Password,
|
|
||||||
NetworkPort,
|
|
||||||
Integer,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _valuespec_special_agent_mailcow():
|
|
||||||
return Dictionary(
|
|
||||||
title=_("Mailcow Server Information"),
|
|
||||||
help=_("Checking Mailcow instances via API"),
|
|
||||||
elements=[
|
|
||||||
(
|
|
||||||
"hostname",
|
|
||||||
TextAscii(
|
|
||||||
title=_("Hostname"),
|
|
||||||
size=32,
|
|
||||||
allow_empty=False,
|
|
||||||
help=_("Hostname of Mailcow server (bare FQDN or IP), mandatory"),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"apikey",
|
|
||||||
IndividualOrStoredPassword(
|
|
||||||
title=_("API Key"),
|
|
||||||
size=32,
|
|
||||||
allow_empty=False,
|
|
||||||
help=_("API Key, mandatory"),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"port",
|
|
||||||
TextAscii(
|
|
||||||
title=_("Port"),
|
|
||||||
allow_empty=True,
|
|
||||||
help=_("Specify port if not listening to HTTPS/HTTP, optional"),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"check_version",
|
|
||||||
Checkbox(
|
|
||||||
title=_("Check version"),
|
|
||||||
help=_("Checks the running version against the public Github repo"),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"no_https",
|
|
||||||
Checkbox(
|
|
||||||
title=_("Disable HTTPS"),
|
|
||||||
help=_(
|
|
||||||
"Activate to disable TLS encryption (not recommended), optional"
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"no_cert_check",
|
|
||||||
Checkbox(
|
|
||||||
title=_("Disable certificate validation"),
|
|
||||||
help=_(
|
|
||||||
"Activate to disable certificate validation (not recommended), optional"
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
optional_keys=[],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
rulespec_registry.register(
|
|
||||||
HostRulespec(
|
|
||||||
group=RulespecGroupDatasourceProgramsApps,
|
|
||||||
name="special_agents:mailcow",
|
|
||||||
valuespec=_valuespec_special_agent_mailcow,
|
|
||||||
)
|
|
||||||
)
|
|
BIN
mailcow/agent_based/__pycache__/mailcow_domains.cpython-312.pyc
Normal file
BIN
mailcow/agent_based/__pycache__/mailcow_domains.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mailcow/agent_based/__pycache__/mailcow_info.cpython-312.pyc
Normal file
BIN
mailcow/agent_based/__pycache__/mailcow_info.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
219
mailcow/agent_based/mailcow_domains.py
Normal file
219
mailcow/agent_based/mailcow_domains.py
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=too-many-locals, line-too-long, too-many-statements
|
||||||
|
"""Mailcow check for domains"""
|
||||||
|
|
||||||
|
|
||||||
|
# import necessary elements from API version 2
|
||||||
|
from cmk.agent_based.v2 import (
|
||||||
|
AgentSection,
|
||||||
|
CheckPlugin,
|
||||||
|
Service,
|
||||||
|
Result,
|
||||||
|
State,
|
||||||
|
Metric,
|
||||||
|
render,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_state_upper(
|
||||||
|
levels: tuple[int | float, int | float], value: int | float
|
||||||
|
) -> State:
|
||||||
|
"""returns OK/WARN/CRIT depending on the given parameters"""
|
||||||
|
warn, crit = levels
|
||||||
|
if value >= crit:
|
||||||
|
return State.CRIT
|
||||||
|
if value >= warn:
|
||||||
|
return State.WARN
|
||||||
|
return State.OK
|
||||||
|
|
||||||
|
|
||||||
|
def parse_mailcow_domains(string_table):
|
||||||
|
"""the parse function"""
|
||||||
|
parsed_data = {}
|
||||||
|
# convert the raw output of the agent section to an meaningful structure
|
||||||
|
# do type conversions and so on
|
||||||
|
for line in string_table:
|
||||||
|
domainname = 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
|
||||||
|
# calculate percentage of used mailboxes
|
||||||
|
max_number_of_mailboxes = int(line[4])
|
||||||
|
number_of_mailboxes = int(line[5])
|
||||||
|
percent_used_mailboxes = number_of_mailboxes * 100 / max_number_of_mailboxes
|
||||||
|
# calculate percentage of used aliases
|
||||||
|
max_number_of_aliases = int(line[6])
|
||||||
|
number_of_aliases = int(line[7])
|
||||||
|
percent_used_aliases = number_of_aliases * 100 / max_number_of_aliases
|
||||||
|
# number of messages within domain
|
||||||
|
total_number_of_messages = int(line[8])
|
||||||
|
# calculate storage used for all messages in domain
|
||||||
|
total_number_of_bytes_used = int(line[9])
|
||||||
|
quota = int(line[10])
|
||||||
|
percent_storage_used_for_messages = total_number_of_bytes_used * 100 / quota
|
||||||
|
# store all (calculated) data
|
||||||
|
parsed_data[f"{domainname}"] = [
|
||||||
|
active,
|
||||||
|
create_time_data,
|
||||||
|
modify_time_data,
|
||||||
|
max_number_of_mailboxes,
|
||||||
|
number_of_mailboxes,
|
||||||
|
percent_used_mailboxes,
|
||||||
|
max_number_of_aliases,
|
||||||
|
number_of_aliases,
|
||||||
|
percent_used_aliases,
|
||||||
|
total_number_of_messages,
|
||||||
|
total_number_of_bytes_used,
|
||||||
|
quota,
|
||||||
|
percent_storage_used_for_messages,
|
||||||
|
]
|
||||||
|
return parsed_data
|
||||||
|
|
||||||
|
|
||||||
|
def discover_mailcow_domains(section):
|
||||||
|
"""the discover function"""
|
||||||
|
# since we have a service with item here we must create one service per item
|
||||||
|
for key in section:
|
||||||
|
yield Service(item=key)
|
||||||
|
|
||||||
|
|
||||||
|
def check_mailcow_domains(item, params, section):
|
||||||
|
"""the check function"""
|
||||||
|
domain = section.get(item)
|
||||||
|
if not domain:
|
||||||
|
# if a previously found domain does not exist anymore, create a meaningful result
|
||||||
|
yield Result(
|
||||||
|
state=State.UNKNOWN,
|
||||||
|
summary="Domain not found anymore, maybe it was deleted?",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# get all infos regarding the domain
|
||||||
|
active = domain[0]
|
||||||
|
create_time = domain[1]
|
||||||
|
modify_time = domain[2]
|
||||||
|
max_number_of_mailboxes = domain[3]
|
||||||
|
number_of_mailboxes = domain[4]
|
||||||
|
percent_used_mailboxes = domain[5]
|
||||||
|
max_number_of_aliases = domain[6]
|
||||||
|
number_of_aliases = domain[7]
|
||||||
|
percent_used_aliases = domain[8]
|
||||||
|
total_number_of_messages = domain[9]
|
||||||
|
total_number_of_bytes_used = domain[10]
|
||||||
|
quota = domain[11]
|
||||||
|
percent_storage_used_for_messages = domain[12]
|
||||||
|
|
||||||
|
# create (main) service for used storage (domain quota)
|
||||||
|
_type, levels = params["levels_mailcow_domains_quota_used"]
|
||||||
|
state_quota = get_state_upper(levels, percent_storage_used_for_messages)
|
||||||
|
|
||||||
|
# create graph for used quota
|
||||||
|
yield Metric(
|
||||||
|
"mailcow_domains_used_quota", percent_storage_used_for_messages, levels=levels
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
# create some additional services and information only in service 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)
|
||||||
|
|
||||||
|
# create service for number of configured mailboxes (percent)
|
||||||
|
_type, levels = params["levels_mailcow_domains_mailboxes_used"]
|
||||||
|
state_mailboxes = get_state_upper(levels, percent_used_mailboxes)
|
||||||
|
yield Metric("mailcow_domains_mailboxes", percent_used_mailboxes, levels=levels)
|
||||||
|
notice = f"Used mailboxes: {render.percent(percent_used_mailboxes)}, {number_of_mailboxes} of {max_number_of_mailboxes} in use"
|
||||||
|
yield Result(state=state_mailboxes, notice=notice)
|
||||||
|
|
||||||
|
# create service for number of configured aliases (percent)
|
||||||
|
_type, levels = params["levels_mailcow_domains_aliases_used"]
|
||||||
|
state_aliases = get_state_upper(levels, percent_used_aliases)
|
||||||
|
yield Metric("mailcow_domains_aliases", percent_used_aliases, levels=levels)
|
||||||
|
notice = f"Used aliases: {render.percent(percent_used_aliases)}, {number_of_aliases} of {max_number_of_aliases} in use"
|
||||||
|
yield Result(state=state_aliases, notice=notice)
|
||||||
|
|
||||||
|
# create service for number of messages
|
||||||
|
_type, levels = params["levels_mailcow_domains_num_messages"]
|
||||||
|
state_messages = get_state_upper(levels, total_number_of_messages)
|
||||||
|
yield Metric("mailcow_domains_messages", total_number_of_messages, levels=levels)
|
||||||
|
notice = f"Number of messages: {total_number_of_messages}"
|
||||||
|
yield Result(state=state_messages, notice=notice)
|
||||||
|
|
||||||
|
# create service for number of configured aliases (absolute)
|
||||||
|
_type, levels = params["levels_mailcow_domains_num_aliases"]
|
||||||
|
state_aliases = get_state_upper(levels, number_of_aliases)
|
||||||
|
yield Metric("mailcow_domains_configured_aliases", number_of_aliases, levels=levels)
|
||||||
|
notice = (
|
||||||
|
f"Number of aliases: {number_of_aliases}, max {max_number_of_aliases} allowed"
|
||||||
|
)
|
||||||
|
yield Result(state=state_aliases, notice=notice)
|
||||||
|
|
||||||
|
# create service for number of configured mailboxes (absolute)
|
||||||
|
_type, levels = params["levels_mailcow_domains_num_mailboxes"]
|
||||||
|
state_mailboxes = get_state_upper(levels, number_of_mailboxes)
|
||||||
|
yield Metric(
|
||||||
|
"mailcow_domains_configured_mailboxes", number_of_mailboxes, levels=levels
|
||||||
|
)
|
||||||
|
notice = f"Number of mailboxes: {number_of_mailboxes}, max {max_number_of_mailboxes} allowed"
|
||||||
|
yield Result(state=state_mailboxes, notice=notice)
|
||||||
|
|
||||||
|
|
||||||
|
# create the new agent section, must begin with "agent_section_"
|
||||||
|
# and must be an instance of "AgentSection"
|
||||||
|
agent_section_mailcow_domains = AgentSection(
|
||||||
|
# "name" must exactly match the section name within the agent output
|
||||||
|
name="mailcow_domains",
|
||||||
|
# define the parse function, name is arbitrary, a good choice is to choose
|
||||||
|
# "parse_" as prefix and append the section name
|
||||||
|
parse_function=parse_mailcow_domains,
|
||||||
|
)
|
||||||
|
|
||||||
|
# create the new check plugin, must begin with "check_plugin_"
|
||||||
|
# and must be an instance of "CheckPlugin"
|
||||||
|
check_plugin_mailcow_domains = CheckPlugin(
|
||||||
|
# "name" should be the same as the corresponding section within the agent output
|
||||||
|
name="mailcow_domains",
|
||||||
|
# this is a service with item, so you have to include a place holder for the item id
|
||||||
|
service_name="Mailcow domain %s",
|
||||||
|
# define the discovery function, name is arbitrary, a good choice is to choose
|
||||||
|
# "discover_" as prefix and append the section name
|
||||||
|
discovery_function=discover_mailcow_domains,
|
||||||
|
# define the check function, name is arbitrary, a good choice is to choose
|
||||||
|
# "check_" as prefix and append the section name
|
||||||
|
check_function=check_mailcow_domains,
|
||||||
|
# define the default parameters
|
||||||
|
check_default_parameters={
|
||||||
|
"levels_mailcow_domains_quota_used": ("fixed", (65.0, 85.0)),
|
||||||
|
"levels_mailcow_domains_mailboxes_used": ("fixed", (65.0, 85.0)),
|
||||||
|
"levels_mailcow_domains_aliases_used": ("fixed", (65.0, 85.0)),
|
||||||
|
"levels_mailcow_domains_num_messages": ("fixed", (10_000, 25_000)),
|
||||||
|
"levels_mailcow_domains_num_aliases": ("fixed", (100, 250)),
|
||||||
|
"levels_mailcow_domains_num_mailboxes": ("fixed", (100, 250)),
|
||||||
|
},
|
||||||
|
# connect to the ruleset where parameters can be defined
|
||||||
|
# must match the name of the ruleset exactly
|
||||||
|
check_ruleset_name="mailcow_domains",
|
||||||
|
)
|
155
mailcow/agent_based/mailcow_info.py
Normal file
155
mailcow/agent_based/mailcow_info.py
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=line-too-long, simplifiable-if-statement, missing-module-docstring, too-many-locals
|
||||||
|
|
||||||
|
# import necessary elements from API version 2
|
||||||
|
from cmk.agent_based.v2 import (
|
||||||
|
AgentSection,
|
||||||
|
CheckPlugin,
|
||||||
|
Service,
|
||||||
|
Result,
|
||||||
|
State,
|
||||||
|
Metric,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_state_upper(
|
||||||
|
levels: tuple[int | float, int | float], value: int | float
|
||||||
|
) -> State:
|
||||||
|
"""returns OK/WARN/CRIT depending on the given parameters"""
|
||||||
|
warn, crit = levels
|
||||||
|
if value >= crit:
|
||||||
|
return State.CRIT
|
||||||
|
if value >= warn:
|
||||||
|
return State.WARN
|
||||||
|
return State.OK
|
||||||
|
|
||||||
|
|
||||||
|
def parse_mailcow_info(string_table) -> dict:
|
||||||
|
"""the parse function"""
|
||||||
|
parsed_data = {}
|
||||||
|
# we only expect one line with 7 entries
|
||||||
|
line = string_table[0]
|
||||||
|
version = line[0]
|
||||||
|
num_domains = int(line[1])
|
||||||
|
num_mailboxes = int(line[2])
|
||||||
|
num_global_messages = int(line[3])
|
||||||
|
git_version = line[4]
|
||||||
|
update_available = line[5]
|
||||||
|
if update_available == "True":
|
||||||
|
update_available = True
|
||||||
|
else:
|
||||||
|
update_available = False
|
||||||
|
check_version_enabled = line[6]
|
||||||
|
if check_version_enabled == "True":
|
||||||
|
check_version_enabled = True
|
||||||
|
else:
|
||||||
|
check_version_enabled = False
|
||||||
|
parsed_data["version"] = version
|
||||||
|
parsed_data["num_domains"] = num_domains
|
||||||
|
parsed_data["num_mailboxes"] = num_mailboxes
|
||||||
|
parsed_data["num_global_messages"] = num_global_messages
|
||||||
|
parsed_data["git_version"] = git_version
|
||||||
|
parsed_data["update_available"] = update_available
|
||||||
|
parsed_data["check_version_enabled"] = check_version_enabled
|
||||||
|
return parsed_data
|
||||||
|
|
||||||
|
|
||||||
|
def discover_mailcow_info(section):
|
||||||
|
"""the discover function"""
|
||||||
|
yield Service()
|
||||||
|
|
||||||
|
|
||||||
|
def check_mailcow_info(params, section):
|
||||||
|
"""the check function"""
|
||||||
|
# get thresholds
|
||||||
|
_type, levels_num_domains = params["levels_num_domains"]
|
||||||
|
_type, levels_num_mailboxes = params["levels_num_mailboxes"]
|
||||||
|
_type, levels_num_global_messages = params["levels_num_global_messages"]
|
||||||
|
# get all section data
|
||||||
|
version: str = section["version"]
|
||||||
|
git_version: str = section["git_version"]
|
||||||
|
check_version_enabled: bool = section["check_version_enabled"]
|
||||||
|
update_available: bool = section["update_available"]
|
||||||
|
num_domains: int = section["num_domains"]
|
||||||
|
num_mailboxes: int = section["num_mailboxes"]
|
||||||
|
num_global_messages: int = section["num_global_messages"]
|
||||||
|
|
||||||
|
# create graphs for number of domains, mailboxes and messages
|
||||||
|
yield Metric(name="mc_num_domains", value=num_domains, levels=levels_num_domains)
|
||||||
|
yield Metric(
|
||||||
|
name="mc_num_mailboxes", value=num_mailboxes, levels=levels_num_mailboxes
|
||||||
|
)
|
||||||
|
yield Metric(
|
||||||
|
name="mc_num_global_messages",
|
||||||
|
value=num_global_messages,
|
||||||
|
levels=levels_num_global_messages,
|
||||||
|
)
|
||||||
|
|
||||||
|
# create overall result
|
||||||
|
if check_version_enabled:
|
||||||
|
if update_available:
|
||||||
|
summary = f"Update available: Running version is {version}, Github version is: {git_version}"
|
||||||
|
state = State.WARN
|
||||||
|
else:
|
||||||
|
summary = f"No update available: Running version is {version}, Github version is: {git_version}"
|
||||||
|
state = State.OK
|
||||||
|
else:
|
||||||
|
summary = f"Version is {version}, Update check is disabled"
|
||||||
|
state = State.OK
|
||||||
|
details = f"Mailcow version: {version}\nNumber of domains: {num_domains}\nNumber of mailboxes: {num_mailboxes}\nNumber of messages: {num_global_messages}"
|
||||||
|
yield Result(state=state, summary=summary, details=details)
|
||||||
|
|
||||||
|
# Create result for number of domains
|
||||||
|
warn, crit = levels_num_domains
|
||||||
|
state = get_state_upper((warn, crit), num_domains)
|
||||||
|
notice = f"Number of domains: {num_domains}"
|
||||||
|
if state != State.OK:
|
||||||
|
yield Result(state=state, notice=notice)
|
||||||
|
|
||||||
|
# Create result for number of mailboxes
|
||||||
|
warn, crit = levels_num_mailboxes
|
||||||
|
state = get_state_upper((warn, crit), num_mailboxes)
|
||||||
|
notice = f"Number of mailboxes: {num_mailboxes}"
|
||||||
|
if state != State.OK:
|
||||||
|
yield Result(state=state, notice=notice)
|
||||||
|
|
||||||
|
# Create result for number of global messages
|
||||||
|
warn, crit = levels_num_global_messages
|
||||||
|
state = get_state_upper((warn, crit), num_global_messages)
|
||||||
|
notice = f"Number of messages: {num_global_messages}"
|
||||||
|
if state != State.OK:
|
||||||
|
yield Result(state=state, notice=notice)
|
||||||
|
|
||||||
|
|
||||||
|
# create the new agent section, must begin with "agent_section_"
|
||||||
|
# and must be an instance of "AgentSection"
|
||||||
|
agent_section_mailcow_info = AgentSection(
|
||||||
|
# "name" must exactly match the section name within the agent output
|
||||||
|
name="mailcow_info",
|
||||||
|
# define the parse function, name is arbitrary, a good choice is to choose
|
||||||
|
# "parse_" as prefix and append the section name
|
||||||
|
parse_function=parse_mailcow_info,
|
||||||
|
)
|
||||||
|
|
||||||
|
# create the new check plugin, must begin with "check_plugin_"
|
||||||
|
# and must be an instance of "CheckPlugin"
|
||||||
|
check_plugin_mailcow_info = CheckPlugin(
|
||||||
|
# "name" should be the same as the corresponding section within the agent output
|
||||||
|
name="mailcow_info",
|
||||||
|
service_name="Mailcow info",
|
||||||
|
# define the discovery function, name is arbitrary, a good choice is to choose
|
||||||
|
# "discover_" as prefix and append the section name
|
||||||
|
discovery_function=discover_mailcow_info,
|
||||||
|
# define the check function, name is arbitrary, a good choice is to choose
|
||||||
|
# "check_" as prefix and append the section name
|
||||||
|
check_function=check_mailcow_info,
|
||||||
|
# define the default parameters
|
||||||
|
check_default_parameters={
|
||||||
|
"levels_num_domains": ("fixed", (100, 200)),
|
||||||
|
"levels_num_mailboxes": ("fixed", (500, 1000)),
|
||||||
|
"levels_num_global_messages": ("fixed", (100_000, 250_000)),
|
||||||
|
},
|
||||||
|
# connect to the ruleset where parameters can be defined
|
||||||
|
# must match the name of the ruleset exactly
|
||||||
|
check_ruleset_name="mailcow_info",
|
||||||
|
)
|
211
mailcow/agent_based/mailcow_mailboxes.py
Normal file
211
mailcow/agent_based/mailcow_mailboxes.py
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=too-many-locals, line-too-long, too-many-statements, too-many-branches
|
||||||
|
"""Mailcow check for mailboxes"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
# import necessary elements from API version 2
|
||||||
|
from cmk.agent_based.v2 import (
|
||||||
|
AgentSection,
|
||||||
|
CheckPlugin,
|
||||||
|
Service,
|
||||||
|
Result,
|
||||||
|
State,
|
||||||
|
Metric,
|
||||||
|
render,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_state_upper(
|
||||||
|
levels: tuple[int | float, int | float], value: int | float
|
||||||
|
) -> State:
|
||||||
|
"""returns OK/WARN/CRIT depending on the given parameters"""
|
||||||
|
warn, crit = levels
|
||||||
|
if value >= crit:
|
||||||
|
return State.CRIT
|
||||||
|
if value >= warn:
|
||||||
|
return State.WARN
|
||||||
|
return State.OK
|
||||||
|
|
||||||
|
|
||||||
|
def parse_mailcow_mailboxes(string_table):
|
||||||
|
"""the parse function"""
|
||||||
|
parsed_data = {}
|
||||||
|
# convert the raw output of the agent section to an meaningful structure
|
||||||
|
# do type conversions and so on
|
||||||
|
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])
|
||||||
|
# calculate storage used for all messages in mailbox
|
||||||
|
quota = int(line[7])
|
||||||
|
total_number_of_bytes_used = int(line[8])
|
||||||
|
if quota == 0:
|
||||||
|
# quota is not set, if this is the case, line[6] contains no numeric value, but the char "-"
|
||||||
|
# so set all usage counters to zero
|
||||||
|
percent_in_use = 0
|
||||||
|
percent_storage_used_for_messages = 0
|
||||||
|
else:
|
||||||
|
# percent in use, rounded to full percent (calculated by Mailcow)
|
||||||
|
percent_in_use = int(line[6])
|
||||||
|
# let's calculate our own value
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
def discover_mailcow_mailboxes(section):
|
||||||
|
"""the discover function"""
|
||||||
|
# since we have a service with item here we must create one service per item
|
||||||
|
for key in section:
|
||||||
|
yield Service(item=key)
|
||||||
|
|
||||||
|
|
||||||
|
def check_mailcow_mailboxes(item, params, section):
|
||||||
|
"""the check function"""
|
||||||
|
mailbox = section.get(item)
|
||||||
|
if not mailbox:
|
||||||
|
# if a previously found domain does not exist anymore, create a meaningful result
|
||||||
|
yield Result(
|
||||||
|
state=State.UNKNOWN,
|
||||||
|
summary="Mailbox not found anymore, maybe it was deleted?",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# get all infos regarding the mailbox
|
||||||
|
active = mailbox[0]
|
||||||
|
create_time = mailbox[1]
|
||||||
|
modify_time = mailbox[2]
|
||||||
|
display_name = mailbox[3]
|
||||||
|
number_of_messages = mailbox[4]
|
||||||
|
_percent_in_use = mailbox[5]
|
||||||
|
quota = mailbox[6]
|
||||||
|
total_number_of_bytes_used = mailbox[7]
|
||||||
|
percent_storage_used_for_messages = mailbox[8]
|
||||||
|
last_imap_login_data = mailbox[9]
|
||||||
|
last_pop3_login_data = mailbox[10]
|
||||||
|
last_smtp_login_data = mailbox[11]
|
||||||
|
|
||||||
|
# create (main) service for used storage (mailbox quota)
|
||||||
|
_type, levels = params["levels_mailcow_mailboxes_quota_used"]
|
||||||
|
state_quota = get_state_upper(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
|
||||||
|
_type, levels = params["levels_mailcow_mailboxes_num_messages"]
|
||||||
|
state_messages = get_state_upper(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)
|
||||||
|
|
||||||
|
|
||||||
|
# create the new agent section, must begin with "agent_section_"
|
||||||
|
# and must be an instance of "AgentSection"
|
||||||
|
agent_section_mailcow_mailboxes = AgentSection(
|
||||||
|
# "name" must exactly match the section name within the agent output
|
||||||
|
name="mailcow_mailboxes",
|
||||||
|
# define the parse function, name is arbitrary, a good choice is to choose
|
||||||
|
# "parse_" as prefix and append the section name
|
||||||
|
parse_function=parse_mailcow_mailboxes,
|
||||||
|
)
|
||||||
|
|
||||||
|
# create the new check plugin, must begin with "check_plugin_"
|
||||||
|
# and must be an instance of "CheckPlugin"
|
||||||
|
check_plugin_mailcow_mailboxes = CheckPlugin(
|
||||||
|
# "name" should be the same as the corresponding section within the agent output
|
||||||
|
name="mailcow_mailboxes",
|
||||||
|
# this is a service with item, so you have to include a place holder for the item id
|
||||||
|
service_name="Mailcow mailbox %s",
|
||||||
|
# define the discovery function, name is arbitrary, a good choice is to choose
|
||||||
|
# "discover_" as prefix and append the section name
|
||||||
|
discovery_function=discover_mailcow_mailboxes,
|
||||||
|
# define the check function, name is arbitrary, a good choice is to choose
|
||||||
|
# "check_" as prefix and append the section name
|
||||||
|
check_function=check_mailcow_mailboxes,
|
||||||
|
# define the default parameters
|
||||||
|
check_default_parameters={
|
||||||
|
"levels_mailcow_mailboxes_quota_used": ("fixed", (65.0, 85.0)),
|
||||||
|
"levels_mailcow_mailboxes_num_messages": ("fixed", (1000, 2500)),
|
||||||
|
},
|
||||||
|
# connect to the ruleset where parameters can be defined
|
||||||
|
# must match the name of the ruleset exactly
|
||||||
|
check_ruleset_name="mailcow_mailboxes",
|
||||||
|
)
|
@ -17,4 +17,4 @@ description:
|
|||||||
item:
|
item:
|
||||||
domainname
|
domainname
|
||||||
inventory:
|
inventory:
|
||||||
one service is created for each domain
|
one service is created for each email domain
|
BIN
mailcow/graphing/__pycache__/graph_mailcow.cpython-312.pyc
Normal file
BIN
mailcow/graphing/__pycache__/graph_mailcow.cpython-312.pyc
Normal file
Binary file not shown.
112
mailcow/graphing/graph_mailcow.py
Normal file
112
mailcow/graphing/graph_mailcow.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=unused-import
|
||||||
|
"""graphing and metrics definitions"""
|
||||||
|
|
||||||
|
from cmk.graphing.v1 import Title
|
||||||
|
from cmk.graphing.v1.graphs import Graph, MinimalRange
|
||||||
|
from cmk.graphing.v1.metrics import Color, DecimalNotation, Metric, Unit
|
||||||
|
from cmk.graphing.v1.perfometers import Closed, FocusRange, Perfometer
|
||||||
|
|
||||||
|
## Metrics
|
||||||
|
# metrics must begin with "metric_" and be an instance of "Metric"
|
||||||
|
|
||||||
|
# Global metrics
|
||||||
|
metric_mc_num_domains = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="mc_num_domains",
|
||||||
|
title=Title("Number of email domains"),
|
||||||
|
unit=Unit(DecimalNotation("")),
|
||||||
|
color=Color.DARK_ORANGE,
|
||||||
|
)
|
||||||
|
metric_mc_num_global_messages = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="mc_num_global_messages",
|
||||||
|
title=Title("Global number of messages"),
|
||||||
|
unit=Unit(DecimalNotation("")),
|
||||||
|
color=Color.DARK_CYAN,
|
||||||
|
)
|
||||||
|
metric_mc_num_mailboxes = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="mc_num_mailboxes",
|
||||||
|
title=Title("Number of mailboxes"),
|
||||||
|
unit=Unit(DecimalNotation("")),
|
||||||
|
color=Color.DARK_GREEN,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Mailbox Metrics
|
||||||
|
|
||||||
|
metric_mc_mailboxes_used_quota = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="mailcow_mailboxes_used_quota",
|
||||||
|
title=Title("Percentage of mailbox quota used"),
|
||||||
|
unit=Unit(DecimalNotation("%")),
|
||||||
|
color=Color.DARK_ORANGE,
|
||||||
|
)
|
||||||
|
metric_mc_mailboxes_messages = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="mailcow_mailboxes_messages",
|
||||||
|
title=Title("Number of messages in mailbox"),
|
||||||
|
unit=Unit(DecimalNotation("")),
|
||||||
|
color=Color.DARK_RED,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Domain metrics
|
||||||
|
metric_mc_domains_used_quota = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="mailcow_domains_used_quota",
|
||||||
|
title=Title("Percentage of domain quota used"),
|
||||||
|
unit=Unit(DecimalNotation("%")),
|
||||||
|
color=Color.DARK_ORANGE,
|
||||||
|
)
|
||||||
|
metric_mc_domains_mailboxes = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="mailcow_domains_mailboxes",
|
||||||
|
title=Title("Percentage of maximum mailboxes used"),
|
||||||
|
unit=Unit(DecimalNotation("%")),
|
||||||
|
color=Color.DARK_GREEN,
|
||||||
|
)
|
||||||
|
metric_mc_domains_aliases = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="mailcow_domains_aliases",
|
||||||
|
title=Title("Percentage of maximum aliases used"),
|
||||||
|
unit=Unit(DecimalNotation("%")),
|
||||||
|
color=Color.DARK_BLUE,
|
||||||
|
)
|
||||||
|
metric_mc_domains_messages = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="mailcow_domains_messages",
|
||||||
|
title=Title("Number of messages"),
|
||||||
|
unit=Unit(DecimalNotation("")),
|
||||||
|
color=Color.DARK_RED,
|
||||||
|
)
|
||||||
|
metric_mc_domains_configured_aliases = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="mailcow_domains_configured_aliases",
|
||||||
|
title=Title("Number of configured aliases"),
|
||||||
|
unit=Unit(DecimalNotation("")),
|
||||||
|
color=Color.DARK_CYAN,
|
||||||
|
)
|
||||||
|
metric_mc_domains_configured_mailboxes = Metric(
|
||||||
|
# "name" must be exactly the "metric_name" within the check function
|
||||||
|
name="mailcow_domains_configured_mailboxes",
|
||||||
|
title=Title("Number of configured mailboxes"),
|
||||||
|
unit=Unit(DecimalNotation("")),
|
||||||
|
color=Color.DARK_PINK,
|
||||||
|
)
|
||||||
|
|
||||||
|
## Perfometers
|
||||||
|
# perfometers must begin with "perfometer_" and be an instance of "Perfometer"
|
||||||
|
|
||||||
|
perfometer_mc_domains_used_quota = Perfometer(
|
||||||
|
name="mailcow_domains_used_quota",
|
||||||
|
focus_range=FocusRange(Closed(0), Closed(100)),
|
||||||
|
# "segments" must be exactly the name of the metric
|
||||||
|
segments=["mailcow_domains_used_quota"],
|
||||||
|
)
|
||||||
|
|
||||||
|
perfometer_mc_mailboxes_used_quota = Perfometer(
|
||||||
|
name="mailcow_mailboxes_used_quota",
|
||||||
|
focus_range=FocusRange(Closed(0), Closed(100)),
|
||||||
|
# "segments" must be exactly the name of the metric
|
||||||
|
segments=["mailcow_mailboxes_used_quota"],
|
||||||
|
)
|
@ -1,206 +1,70 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=line-too-long, too-many-branches, too-many-locals
|
||||||
|
# pylint: disable=bare-except, pointless-string-statement, consider-using-dict-items
|
||||||
|
# pylint: disable=too-many-arguments, too-many-statements, simplifiable-if-statement, too-many-positional-arguments
|
||||||
|
# pylint: disable=possibly-used-before-assignment, used-before-assignment
|
||||||
|
# pylint: disable=missing-class-docstring, missing-module-docstring, missing-function-docstring
|
||||||
|
"""CheckMK special agent for Mailcow systems"""
|
||||||
|
|
||||||
import getopt
|
import json
|
||||||
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
import requests
|
import requests
|
||||||
import urllib3
|
import urllib3
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import cmk.utils.password_store
|
|
||||||
from pprint import pprint
|
|
||||||
from requests.structures import CaseInsensitiveDict
|
from requests.structures import CaseInsensitiveDict
|
||||||
from requests.auth import HTTPBasicAuth
|
|
||||||
from time import (
|
|
||||||
time,
|
|
||||||
localtime,
|
|
||||||
strftime,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def showUsage() -> None:
|
def get_args() -> argparse.Namespace:
|
||||||
sys.stderr.write(
|
parser: argparse.ArgumentParser = argparse.ArgumentParser(
|
||||||
"""CheckMK Mailcow Special Agent
|
description="Mailcow server parameters"
|
||||||
|
|
||||||
USAGE: agent_nextcloud -H [hostname] -k [apikey]
|
|
||||||
agent_nextcloud -h
|
|
||||||
|
|
||||||
OPTIONS:
|
|
||||||
-H, --hostname Hostname (FQDN or IP) of Nextcloud server
|
|
||||||
-k, --apikey API Key
|
|
||||||
-P, --port Port
|
|
||||||
--check-version True|False If "True": Running version will be checked against official Github repo
|
|
||||||
--no-https True|False If "True": Disable HTTPS, use HTTP (not recommended!)
|
|
||||||
--no-cert-check True|False If "True": Disable TLS certificate check (not recommended!)
|
|
||||||
-h, --help Show this help message and exit
|
|
||||||
"""
|
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--hostname", required=True, type=str, help="Hostname or IP of mailcow server"
|
||||||
# set this to True to produce debug output (this clutters the agent output)
|
|
||||||
# be aware: activating this logs very sensitive information to debug files in ~/tmp
|
|
||||||
# !!DO NOT FORGET to delete these files after debugging is done!!
|
|
||||||
|
|
||||||
DEBUG = False
|
|
||||||
|
|
||||||
mc_api_base = "api/v1/get"
|
|
||||||
|
|
||||||
opt_hostname = ""
|
|
||||||
opt_apikey = ""
|
|
||||||
opt_port = ""
|
|
||||||
opt_check_version = False
|
|
||||||
opt_no_https = False
|
|
||||||
opt_no_cert_check = False
|
|
||||||
|
|
||||||
short_options = "hH:k:P:"
|
|
||||||
long_options = [
|
|
||||||
"hostname=",
|
|
||||||
"apikey=",
|
|
||||||
"port=",
|
|
||||||
"check-version=",
|
|
||||||
"no-https=",
|
|
||||||
"no-cert-check=",
|
|
||||||
"help",
|
|
||||||
]
|
|
||||||
|
|
||||||
domain_data = {}
|
|
||||||
mailbox_data = {}
|
|
||||||
|
|
||||||
debugLogFilename = ""
|
|
||||||
SEP = "|"
|
|
||||||
# SEP = "\t"
|
|
||||||
TIMEFMT = "%Y-%m-%d %H:%M:%S"
|
|
||||||
FLOATFMT = "{:.4f}"
|
|
||||||
|
|
||||||
"""
|
|
||||||
Decorator function for debugging purposes
|
|
||||||
creates a file with many information regarding the function call, like:
|
|
||||||
timestamp
|
|
||||||
name of function
|
|
||||||
runtime
|
|
||||||
number of arguments
|
|
||||||
number of keyword arguments
|
|
||||||
return value of function call
|
|
||||||
type of return value
|
|
||||||
all parameters given to function
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def debugLog(function):
|
|
||||||
def wrapper(*args, **kwargs):
|
|
||||||
# execute function and measure runtime
|
|
||||||
start = time()
|
|
||||||
value = function(*args, **kwargs)
|
|
||||||
end = time()
|
|
||||||
# get number of args and kwargs
|
|
||||||
len_args = len(args)
|
|
||||||
len_kwargs = len(kwargs)
|
|
||||||
# format the output
|
|
||||||
seconds = FLOATFMT.format(end - start)
|
|
||||||
local_time = strftime(TIMEFMT, localtime(start))
|
|
||||||
# get function name
|
|
||||||
fname = function.__name__
|
|
||||||
# create output
|
|
||||||
# out1: Timestamp|Name of Function|Runtime|Num Args|Num Kwargs|Return Value|Return Value Type
|
|
||||||
out1 = f"{local_time}{SEP}{fname}{SEP}{seconds}{SEP}{len_args}{SEP}{len_kwargs}{SEP}{value}{SEP}{type(value)}"
|
|
||||||
# out2: all arguments
|
|
||||||
out2 = ""
|
|
||||||
for arg in args:
|
|
||||||
out2 = out2 + SEP + str(arg)
|
|
||||||
# out3: all keyword arguments
|
|
||||||
out3 = ""
|
|
||||||
if len_kwargs > 0:
|
|
||||||
for key, val in kwargs.items():
|
|
||||||
out3 = out3 + SEP + key + ":" + str(val)
|
|
||||||
# write output to file
|
|
||||||
if debugLogFilename != "":
|
|
||||||
try:
|
|
||||||
with open(debugLogFilename, "a+") as f:
|
|
||||||
f.write(f"{out1}{out2}{out3}\n")
|
|
||||||
except:
|
|
||||||
sys.stderr.write(
|
|
||||||
f"Something went wrong when writing to file {debugLogFilename}\n"
|
|
||||||
)
|
)
|
||||||
sys.exit(1)
|
parser.add_argument("--apikey", required=True, type=str, help="API key")
|
||||||
else:
|
parser.add_argument(
|
||||||
sys.stderr.write(f"Debug activated, but no debug filename given.\n")
|
"--port",
|
||||||
sys.exit(1)
|
required=False,
|
||||||
return value
|
type=int,
|
||||||
|
help="Port where the server is listening on",
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
def getDebugFilename(hostname: str) -> str:
|
|
||||||
home_path = os.getenv("HOME")
|
|
||||||
tmp_path = f"{home_path}/tmp"
|
|
||||||
file_name = f"{tmp_path}/mailcow_{hostname}_debug.log"
|
|
||||||
return file_name
|
|
||||||
|
|
||||||
|
|
||||||
def getOptions() -> None:
|
|
||||||
global opt_hostname
|
|
||||||
global opt_apikey
|
|
||||||
global opt_port
|
|
||||||
global opt_check_version
|
|
||||||
global opt_no_https
|
|
||||||
global opt_no_cert_check
|
|
||||||
|
|
||||||
opts, args = getopt.getopt(sys.argv[1:], short_options, long_options)
|
|
||||||
for opt, arg in opts:
|
|
||||||
if opt in ["-H", "--hostname"]:
|
|
||||||
opt_hostname = arg
|
|
||||||
elif opt in ["-k", "--apikey"]:
|
|
||||||
opt_apikey = arg
|
|
||||||
elif opt in ["-P", "--port"]:
|
|
||||||
opt_port = arg
|
|
||||||
elif opt in ["--check-version"]:
|
|
||||||
if arg == "True":
|
|
||||||
opt_check_version = True
|
|
||||||
else:
|
|
||||||
opt_check_version = False
|
|
||||||
elif opt in ["--no-https"]:
|
|
||||||
if arg == "True":
|
|
||||||
opt_no_https = True
|
|
||||||
else:
|
|
||||||
opt_no_https = False
|
|
||||||
elif opt in ["--no-cert-check"]:
|
|
||||||
if arg == "True":
|
|
||||||
opt_no_cert_check = True
|
|
||||||
else:
|
|
||||||
opt_no_cert_check = False
|
|
||||||
elif opt in ["-h", "--help"]:
|
|
||||||
showUsage()
|
|
||||||
sys.exit(0)
|
|
||||||
if DEBUG:
|
|
||||||
home_path = os.getenv("HOME")
|
|
||||||
tmp_path = f"{home_path}/tmp"
|
|
||||||
help_file = f"{tmp_path}/mailcow_{opt_hostname}_debug.txt"
|
|
||||||
with open(help_file, "a") as file:
|
|
||||||
file.write(
|
|
||||||
f"Number of Arguments: {len(sys.argv)}, Argument List: {str(sys.argv)}\n"
|
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--no-https",
|
||||||
# @debugLog
|
required=False,
|
||||||
def showOptions() -> None:
|
default=False,
|
||||||
print(f"Hostname: {opt_hostname}")
|
help="Disable HTTPS",
|
||||||
print(f"Username: {opt_apikey}")
|
action="store_true",
|
||||||
print(f"Port: {opt_port}")
|
|
||||||
print(f"Check Version: {opt_check_version}")
|
|
||||||
print(f"No HTTPS: {opt_no_https}")
|
|
||||||
print(f"No TLS Check: {opt_no_cert_check}")
|
|
||||||
home_path = os.getenv("HOME")
|
|
||||||
tmp_path = f"{home_path}/tmp"
|
|
||||||
help_file = f"{tmp_path}/mailcow_{opt_hostname}_debug.txt"
|
|
||||||
with open(help_file, "a") as file:
|
|
||||||
file.write(
|
|
||||||
f"Hostname: {opt_hostname}, Port: {opt_port}, No HTTPS: {opt_no_https}, No Cert Check: {opt_no_cert_check}\n"
|
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--no-cert-check",
|
||||||
|
required=False,
|
||||||
|
default=False,
|
||||||
|
help="Disable certificate checks",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--check-version",
|
||||||
|
required=False,
|
||||||
|
default=False,
|
||||||
|
help="Enable version check",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
# @debugLog
|
MC_API_BASE: str = "api/v1/get"
|
||||||
def getDomainInfo(headers: str, verify: bool, base_url: str) -> int:
|
TIMEOUT: int = 30
|
||||||
url = f"{base_url}/domain/all"
|
|
||||||
response = requests.get(url, headers=headers, verify=verify)
|
domain_data: dict = {}
|
||||||
|
mailbox_data: dict = {}
|
||||||
|
|
||||||
|
|
||||||
|
def get_domain_info(headers: str, verify: bool, base_url: str) -> int:
|
||||||
|
"""retrieves info about all configured domains"""
|
||||||
|
url: str = f"{base_url}/domain/all"
|
||||||
|
response = requests.get(url=url, headers=headers, verify=verify, timeout=TIMEOUT)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
jsdata = response.text
|
jsdata = response.text
|
||||||
data = json.loads(jsdata) # returns a list of dictionaries
|
data = json.loads(jsdata) # returns a list of dictionaries
|
||||||
@ -243,22 +107,21 @@ def getDomainInfo(headers: str, verify: bool, base_url: str) -> int:
|
|||||||
i += 1
|
i += 1
|
||||||
# return number of email domains
|
# return number of email domains
|
||||||
return i
|
return i
|
||||||
else:
|
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
f"Request response code is {response.status_code} with URL {url}\n"
|
f"Request response code is {response.status_code} with URL {url}\n"
|
||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
# @debugLog
|
def get_mailbox_info(headers: str, verify: bool, base_url: str) -> tuple:
|
||||||
def getMailboxInfo(headers: str, verify: bool, base_url: str) -> tuple:
|
"""retrieves info about all configured mailboxes"""
|
||||||
url = f"{base_url}/mailbox/all"
|
url: str = f"{base_url}/mailbox/all"
|
||||||
response = requests.get(url, headers=headers, verify=verify)
|
response = requests.get(url=url, headers=headers, verify=verify, timeout=TIMEOUT)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
jsdata = response.text
|
jsdata = response.text
|
||||||
data = json.loads(jsdata) # returns a list of dictionaries
|
data = json.loads(jsdata) # returns a list of dictionaries
|
||||||
i = 0
|
i: int = 0
|
||||||
global_num_messages = 0
|
global_num_messages: int = 0
|
||||||
while i < len(data):
|
while i < len(data):
|
||||||
# get status of mailbox (0-->inactive or 1-->active)
|
# get status of mailbox (0-->inactive or 1-->active)
|
||||||
active = data[i].get("active")
|
active = data[i].get("active")
|
||||||
@ -282,7 +145,7 @@ def getMailboxInfo(headers: str, verify: bool, base_url: str) -> tuple:
|
|||||||
last_imap_login = data[i].get("last_imap_login")
|
last_imap_login = data[i].get("last_imap_login")
|
||||||
last_pop3_login = data[i].get("last_pop3_login")
|
last_pop3_login = data[i].get("last_pop3_login")
|
||||||
last_smtp_login = data[i].get("last_smtp_login")
|
last_smtp_login = data[i].get("last_smtp_login")
|
||||||
mb = {
|
mailbox = {
|
||||||
"active": active,
|
"active": active,
|
||||||
"created": created,
|
"created": created,
|
||||||
"modified": modified,
|
"modified": modified,
|
||||||
@ -297,27 +160,26 @@ def getMailboxInfo(headers: str, verify: bool, base_url: str) -> tuple:
|
|||||||
"last_smtp_login": last_smtp_login,
|
"last_smtp_login": last_smtp_login,
|
||||||
}
|
}
|
||||||
mailbox_data[username] = {}
|
mailbox_data[username] = {}
|
||||||
mailbox_data[username] = mb
|
mailbox_data[username] = mailbox
|
||||||
i += 1
|
i += 1
|
||||||
global_num_messages += num_messages
|
global_num_messages += num_messages
|
||||||
# return number of mailboxes and global number of messages
|
# return number of mailboxes and global number of messages
|
||||||
return i, global_num_messages
|
return i, global_num_messages
|
||||||
else:
|
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
f"Request response code is {response.status_code} with URL {url}\n"
|
f"Request response code is {response.status_code} with URL {url}\n"
|
||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def getGitVersion() -> str:
|
def get_git_version() -> str:
|
||||||
url = "https://api.github.com/repos/mailcow/mailcow-dockerized/releases/latest"
|
"""gets the actual version of Mailcow from Github"""
|
||||||
git_version = ""
|
url: str = "https://api.github.com/repos/mailcow/mailcow-dockerized/releases/latest"
|
||||||
response = requests.get(url)
|
git_version: str = ""
|
||||||
|
response = requests.get(url=url, timeout=TIMEOUT)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
jsdata = response.text
|
jsdata = response.text
|
||||||
data = json.loads(jsdata) # returns a dictionary
|
data = json.loads(jsdata) # returns a dictionary
|
||||||
git_version = data["tag_name"]
|
git_version = data["tag_name"]
|
||||||
# print(git_version)
|
|
||||||
else:
|
else:
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
f"Request response code is {response.status_code} with URL {url}\n"
|
f"Request response code is {response.status_code} with URL {url}\n"
|
||||||
@ -326,8 +188,9 @@ def getGitVersion() -> str:
|
|||||||
return git_version
|
return git_version
|
||||||
|
|
||||||
|
|
||||||
def compareVersions(mc_ver: str, git_ver: str) -> bool:
|
def compare_versions(mc_ver: str, git_ver: str) -> bool:
|
||||||
update_available = False
|
"""compares the actual Github version with the version of the running Mailcow system"""
|
||||||
|
update_available: bool = False
|
||||||
try:
|
try:
|
||||||
mc_year, mc_month = mc_ver.split("-")
|
mc_year, mc_month = mc_ver.split("-")
|
||||||
git_year, git_month = git_ver.split("-")
|
git_year, git_month = git_ver.split("-")
|
||||||
@ -360,15 +223,18 @@ def compareVersions(mc_ver: str, git_ver: str) -> bool:
|
|||||||
elif git_month_ver > mc_month_ver:
|
elif git_month_ver > mc_month_ver:
|
||||||
update_available = True
|
update_available = True
|
||||||
except:
|
except:
|
||||||
|
# TBD
|
||||||
pass
|
pass
|
||||||
return update_available
|
return update_available
|
||||||
|
|
||||||
|
|
||||||
# @debugLog
|
def get_mailcow_info(
|
||||||
def getMailcowInfo(headers: str, verify: bool, base_url: str) -> dict:
|
headers: str, verify: bool, base_url: str, check_version: bool
|
||||||
|
) -> dict:
|
||||||
|
"""retrieves several global information about the mailcow system"""
|
||||||
info_data = {}
|
info_data = {}
|
||||||
url = f"{base_url}/status/version"
|
url = f"{base_url}/status/version"
|
||||||
response = requests.get(url, headers=headers, verify=verify)
|
response = requests.get(url=url, headers=headers, verify=verify, timeout=TIMEOUT)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
jsdata = response.text
|
jsdata = response.text
|
||||||
data = json.loads(jsdata) # returns a dictionary
|
data = json.loads(jsdata) # returns a dictionary
|
||||||
@ -376,20 +242,17 @@ def getMailcowInfo(headers: str, verify: bool, base_url: str) -> dict:
|
|||||||
# get Mailcow version
|
# get Mailcow version
|
||||||
mc_version = data["version"]
|
mc_version = data["version"]
|
||||||
# if enabled, check this version against the official Mailcow repo on Github
|
# if enabled, check this version against the official Mailcow repo on Github
|
||||||
if opt_check_version:
|
if check_version:
|
||||||
git_version = getGitVersion()
|
git_version = get_git_version()
|
||||||
update_available = compareVersions(mc_version, git_version)
|
update_available = compare_versions(mc_version, git_version)
|
||||||
# update_available = compareVersions("2023-01a", "2023-02")
|
|
||||||
# print(update_available)
|
|
||||||
info_data["git_version"] = git_version
|
info_data["git_version"] = git_version
|
||||||
info_data["update_available"] = update_available
|
info_data["update_available"] = update_available
|
||||||
else:
|
else:
|
||||||
info_data["git_version"] = "Version check disabled"
|
info_data["git_version"] = "Version check disabled"
|
||||||
info_data["update_available"] = False
|
info_data["update_available"] = False
|
||||||
info_data["mc_version"] = mc_version
|
info_data["mc_version"] = mc_version
|
||||||
info_data["check_version_enabled"] = opt_check_version
|
info_data["check_version_enabled"] = check_version
|
||||||
return info_data
|
return info_data
|
||||||
else:
|
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
f"Request response code is {response.status_code} with URL {url}\n"
|
f"Request response code is {response.status_code} with URL {url}\n"
|
||||||
)
|
)
|
||||||
@ -418,8 +281,8 @@ user1@dom2.de;1;2022-04-30 09:55:37;2022-04-30 09:55:37;Melissa;53460;33;1996488
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
# @debugLog
|
def do_cmk_output_mailboxes() -> None:
|
||||||
def doCmkOutputMailboxes() -> None:
|
"""prints out agent section for mailboxes"""
|
||||||
print("<<<mailcow_mailboxes:sep(59)>>>")
|
print("<<<mailcow_mailboxes:sep(59)>>>")
|
||||||
for mb in mailbox_data:
|
for mb in mailbox_data:
|
||||||
active = mailbox_data[mb]["active"]
|
active = mailbox_data[mb]["active"]
|
||||||
@ -440,8 +303,7 @@ def doCmkOutputMailboxes() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# @debugLog
|
def do_cmk_output_mailcow(
|
||||||
def doCmkOutputMailcow(
|
|
||||||
version: str,
|
version: str,
|
||||||
num_domains: int,
|
num_domains: int,
|
||||||
num_mailboxes: int,
|
num_mailboxes: int,
|
||||||
@ -450,6 +312,7 @@ def doCmkOutputMailcow(
|
|||||||
update_available: bool,
|
update_available: bool,
|
||||||
check_version_enabled: bool,
|
check_version_enabled: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""prints out agent section for global mailcow info"""
|
||||||
print("<<<mailcow_info:sep(59)>>>")
|
print("<<<mailcow_info:sep(59)>>>")
|
||||||
# strip semicolons, if present, since we use it as delimiter
|
# strip semicolons, if present, since we use it as delimiter
|
||||||
version = version.replace(";", "")
|
version = version.replace(";", "")
|
||||||
@ -460,11 +323,11 @@ def doCmkOutputMailcow(
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
Output is as follows:
|
Output is as follows:
|
||||||
0 domain_name
|
0 domain name
|
||||||
1 active 1 --> active, 0 --> not active
|
1 active 1 --> active, 0 --> not active
|
||||||
2 creation date "None" if ???
|
2 creation date "None" if ???
|
||||||
3 last modified date "None" if never modified
|
3 last modified date "None" if never modified
|
||||||
4 max number mailboxes
|
4 max number of mailboxes
|
||||||
5 number of mailboxes
|
5 number of mailboxes
|
||||||
6 max number of aliases
|
6 max number of aliases
|
||||||
7 number of aliases
|
7 number of aliases
|
||||||
@ -479,8 +342,8 @@ dom3.de;1;2022-04-29 13:36:08;2022-04-29 21:26:19;10;1;100;3;28132;12852485367;2
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
# @debugLog
|
def do_cmk_output_domains() -> None:
|
||||||
def doCmkOutputDomains() -> None:
|
"""print out agent section for domains"""
|
||||||
print("<<<mailcow_domains:sep(59)>>>")
|
print("<<<mailcow_domains:sep(59)>>>")
|
||||||
for dom in domain_data:
|
for dom in domain_data:
|
||||||
active = domain_data[dom]["active"]
|
active = domain_data[dom]["active"]
|
||||||
@ -499,74 +362,77 @@ def doCmkOutputDomains() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global debugLogFilename
|
"""main function"""
|
||||||
cmk.utils.password_store.replace_passwords()
|
# get and check parameters
|
||||||
getOptions()
|
params: argparse.Namespace = get_args()
|
||||||
# do some parameter checks
|
# do some parameter checks
|
||||||
if opt_hostname == "":
|
if params.hostname is None:
|
||||||
sys.stderr.write(f"No hostname given.\n")
|
sys.stderr.write("No hostname given.\n")
|
||||||
showUsage()
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
hostname = opt_hostname
|
hostname = params.hostname
|
||||||
if opt_apikey == "":
|
if params.apikey is None:
|
||||||
sys.stderr.write(f"No API key given.\n")
|
sys.stderr.write("No API key given.\n")
|
||||||
showUsage()
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if opt_no_cert_check:
|
else:
|
||||||
|
apikey = params.apikey
|
||||||
|
if params.no_cert_check:
|
||||||
# disable certificate warnings
|
# disable certificate warnings
|
||||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||||
verify = False
|
verify = False
|
||||||
else:
|
else:
|
||||||
verify = True
|
verify = True
|
||||||
if opt_port == "":
|
if params.check_version:
|
||||||
if opt_no_https:
|
check_version = True
|
||||||
|
else:
|
||||||
|
check_version = False
|
||||||
|
if params.port is None:
|
||||||
|
if params.no_https:
|
||||||
protocol = "http"
|
protocol = "http"
|
||||||
port = "80"
|
port = "80"
|
||||||
else:
|
else:
|
||||||
protocol = "https"
|
protocol = "https"
|
||||||
port = "443"
|
port = "443"
|
||||||
else:
|
else:
|
||||||
if opt_no_https:
|
if params.no_https:
|
||||||
protocol = "http"
|
protocol = "http"
|
||||||
else:
|
else:
|
||||||
protocol = "https"
|
protocol = "https"
|
||||||
port = opt_port
|
port = params.port
|
||||||
if protocol == "http" and port == "443":
|
if protocol == "http" and port == "443":
|
||||||
sys.stderr.write(f"Combining HTTP with port 443 is not supported.\n")
|
sys.stderr.write("Combining HTTP with port 443 is not supported.\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if protocol == "https" and port == "80":
|
if protocol == "https" and port == "80":
|
||||||
sys.stderr.write(f"Combining HTTPS with port 80 is not supported.\n")
|
sys.stderr.write("Combining HTTPS with port 80 is not supported.\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
headers = CaseInsensitiveDict()
|
headers = CaseInsensitiveDict()
|
||||||
headers["Accept"] = "application/json"
|
headers["Accept"] = "application/json"
|
||||||
headers["X-API-Key"] = opt_apikey
|
headers["X-API-Key"] = apikey
|
||||||
# now "hostname" contains the FQDN of the host running Mailcow
|
# now "hostname" contains the FQDN of the host running Mailcow
|
||||||
# now "protocol" is http or https
|
# now "protocol" is http or https
|
||||||
# now "port" contains the port number to use
|
# now "port" contains the port number to use
|
||||||
# now "verify" signals whether certificate checking will be done (True) or not (False)
|
# now "verify" signals whether certificate checking will be done (True) or not (False)
|
||||||
|
# now "check_version" signals whether the Mailcow version will be checked against the Github version
|
||||||
# now "headers" contains the accepted format (JSON) and the API key to use
|
# now "headers" contains the accepted format (JSON) and the API key to use
|
||||||
debugLogFilename = getDebugFilename(hostname)
|
base_url = f"{protocol}://{hostname}:{port}/{MC_API_BASE}"
|
||||||
if DEBUG:
|
|
||||||
showOptions()
|
|
||||||
print(
|
|
||||||
f"hostname: {hostname}, protocol: {protocol}, port: {port}, verify: {verify}"
|
|
||||||
)
|
|
||||||
base_url = f"{protocol}://{hostname}:{port}/{mc_api_base}"
|
|
||||||
# get domain data
|
# get domain data
|
||||||
num_domains = getDomainInfo(headers, verify, base_url)
|
num_domains = get_domain_info(headers=headers, verify=verify, base_url=base_url)
|
||||||
# get mailbox data
|
# get mailbox data
|
||||||
num_mailboxes, num_global_messages = getMailboxInfo(headers, verify, base_url)
|
num_mailboxes, num_global_messages = get_mailbox_info(
|
||||||
|
headers=headers, verify=verify, base_url=base_url
|
||||||
|
)
|
||||||
# get global Mailcow info
|
# get global Mailcow info
|
||||||
mailcow_info = getMailcowInfo(headers, verify, base_url)
|
mailcow_info = get_mailcow_info(
|
||||||
|
headers=headers, verify=verify, base_url=base_url, check_version=check_version
|
||||||
|
)
|
||||||
mailcow_version = mailcow_info["mc_version"]
|
mailcow_version = mailcow_info["mc_version"]
|
||||||
github_version = mailcow_info["git_version"]
|
github_version = mailcow_info["git_version"]
|
||||||
update_available = mailcow_info["update_available"]
|
update_available = mailcow_info["update_available"]
|
||||||
check_version_enabled = mailcow_info["check_version_enabled"]
|
check_version_enabled = mailcow_info["check_version_enabled"]
|
||||||
# create agent output
|
# create agent output
|
||||||
doCmkOutputDomains()
|
do_cmk_output_domains()
|
||||||
doCmkOutputMailboxes()
|
do_cmk_output_mailboxes()
|
||||||
doCmkOutputMailcow(
|
do_cmk_output_mailcow(
|
||||||
mailcow_version,
|
mailcow_version,
|
||||||
num_domains,
|
num_domains,
|
||||||
num_mailboxes,
|
num_mailboxes,
|
BIN
mailcow/rulesets/__pycache__/rs_mailcow_domains.cpython-312.pyc
Normal file
BIN
mailcow/rulesets/__pycache__/rs_mailcow_domains.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mailcow/rulesets/__pycache__/rs_mailcow_info.cpython-312.pyc
Normal file
BIN
mailcow/rulesets/__pycache__/rs_mailcow_info.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
mailcow/rulesets/__pycache__/rs_mailcow_params.cpython-312.pyc
Normal file
BIN
mailcow/rulesets/__pycache__/rs_mailcow_params.cpython-312.pyc
Normal file
Binary file not shown.
93
mailcow/rulesets/rs_mailcow_domains.py
Normal file
93
mailcow/rulesets/rs_mailcow_domains.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#!/user/bin/env python3
|
||||||
|
"""parameter form ruleset for mailcow domains"""
|
||||||
|
|
||||||
|
from cmk.rulesets.v1 import Title
|
||||||
|
from cmk.rulesets.v1.form_specs import (
|
||||||
|
DefaultValue,
|
||||||
|
DictElement,
|
||||||
|
Dictionary,
|
||||||
|
LevelDirection,
|
||||||
|
SimpleLevels,
|
||||||
|
Percentage,
|
||||||
|
Integer,
|
||||||
|
)
|
||||||
|
from cmk.rulesets.v1.rule_specs import CheckParameters, HostAndItemCondition, Topic
|
||||||
|
|
||||||
|
|
||||||
|
# function name should begin with an underscore to limit it's visibility
|
||||||
|
def _parameter_form():
|
||||||
|
return Dictionary(
|
||||||
|
elements={
|
||||||
|
"levels_mailcow_domains_quota_used": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Mailcow domains quota usage for storage"),
|
||||||
|
form_spec_template=Percentage(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(65.0, 85.0)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
"levels_mailcow_domains_mailboxes_used": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Mailcow domains mailboxes usage"),
|
||||||
|
form_spec_template=Percentage(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(65.0, 85.0)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
"levels_mailcow_domains_aliases_used": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Mailcow domains aliases usage"),
|
||||||
|
form_spec_template=Percentage(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(65.0, 85.0)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
"levels_mailcow_domains_num_messages": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Number of messages"),
|
||||||
|
form_spec_template=Integer(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(10_000, 25_000)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
"levels_mailcow_domains_num_aliases": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Number of configured aliases"),
|
||||||
|
form_spec_template=Integer(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(100, 250)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
"levels_mailcow_domains_num_mailboxes": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Number of configured mailboxes"),
|
||||||
|
form_spec_template=Integer(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(100, 250)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# name must begin with "rule_spec_", should refer to the used check plugin
|
||||||
|
# must be an instance of "CheckParameters"
|
||||||
|
rule_spec_mailcow_domains = CheckParameters(
|
||||||
|
# "name" should be the same as the check plugin
|
||||||
|
name="mailcow_domains",
|
||||||
|
# the title is shown in the GUI
|
||||||
|
title=Title("Mailcow domain levels"),
|
||||||
|
# this ruleset can be found under Setup|Service monitoring rules|Various
|
||||||
|
topic=Topic.APPLICATIONS,
|
||||||
|
# define the name of the function which creates the GUI elements
|
||||||
|
parameter_form=_parameter_form,
|
||||||
|
# define the label in the GUI where you can restrict the
|
||||||
|
# settings to one or mor specific users (item)
|
||||||
|
condition=HostAndItemCondition(item_title=Title("Domain")),
|
||||||
|
)
|
65
mailcow/rulesets/rs_mailcow_info.py
Normal file
65
mailcow/rulesets/rs_mailcow_info.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
defines the form for typing in all needed levels
|
||||||
|
regarding number of domains, mailboxes and global message count
|
||||||
|
"""
|
||||||
|
|
||||||
|
from cmk.rulesets.v1 import Help, Title
|
||||||
|
from cmk.rulesets.v1.form_specs import (
|
||||||
|
DictElement,
|
||||||
|
Dictionary,
|
||||||
|
SimpleLevels,
|
||||||
|
LevelDirection,
|
||||||
|
DefaultValue,
|
||||||
|
Integer,
|
||||||
|
)
|
||||||
|
from cmk.rulesets.v1.rule_specs import (
|
||||||
|
CheckParameters,
|
||||||
|
Topic,
|
||||||
|
HostCondition,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _parameter_form() -> Dictionary:
|
||||||
|
return Dictionary(
|
||||||
|
title=Title("Levels for global Mailcow information"),
|
||||||
|
help_text=Help("Checking Mailcow systems via API"),
|
||||||
|
elements={
|
||||||
|
"levels_num_domains": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Levels for number of email domains"),
|
||||||
|
form_spec_template=Integer(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(100, 200)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
"levels_num_mailboxes": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Levels for number of mailboxes"),
|
||||||
|
form_spec_template=Integer(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(500, 1000)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
"levels_num_global_messages": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Levels for number of messages"),
|
||||||
|
form_spec_template=Integer(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(100_000, 250_000)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
rule_spec_mailcow_info = CheckParameters(
|
||||||
|
name="mailcow_info",
|
||||||
|
title=Title("Mailcow global levels"),
|
||||||
|
topic=Topic.APPLICATIONS,
|
||||||
|
parameter_form=_parameter_form,
|
||||||
|
condition=HostCondition(),
|
||||||
|
)
|
57
mailcow/rulesets/rs_mailcow_mailboxes.py
Normal file
57
mailcow/rulesets/rs_mailcow_mailboxes.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#!/user/bin/env python3
|
||||||
|
"""parameter form ruleset for mailcow domains"""
|
||||||
|
|
||||||
|
from cmk.rulesets.v1 import Title
|
||||||
|
from cmk.rulesets.v1.form_specs import (
|
||||||
|
DefaultValue,
|
||||||
|
DictElement,
|
||||||
|
Dictionary,
|
||||||
|
LevelDirection,
|
||||||
|
SimpleLevels,
|
||||||
|
Percentage,
|
||||||
|
Integer,
|
||||||
|
)
|
||||||
|
from cmk.rulesets.v1.rule_specs import CheckParameters, HostAndItemCondition, Topic
|
||||||
|
|
||||||
|
|
||||||
|
# function name should begin with an underscore to limit it's visibility
|
||||||
|
def _parameter_form():
|
||||||
|
return Dictionary(
|
||||||
|
elements={
|
||||||
|
"levels_mailcow_mailboxes_quota_used": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Mailcow mailbox quota usage for storage"),
|
||||||
|
form_spec_template=Percentage(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(65.0, 85.0)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
"levels_mailcow_mailboxes_num_messages": DictElement(
|
||||||
|
parameter_form=SimpleLevels(
|
||||||
|
title=Title("Number of messages in mailbox"),
|
||||||
|
form_spec_template=Integer(),
|
||||||
|
level_direction=LevelDirection.UPPER,
|
||||||
|
prefill_fixed_levels=DefaultValue(value=(1000, 2500)),
|
||||||
|
),
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# name must begin with "rule_spec_", should refer to the used check plugin
|
||||||
|
# must be an instance of "CheckParameters"
|
||||||
|
rule_spec_mailcow_mailboxes = CheckParameters(
|
||||||
|
# "name" should be the same as the check plugin
|
||||||
|
name="mailcow_mailboxes",
|
||||||
|
# the title is shown in the GUI
|
||||||
|
title=Title("Mailcow mailbox levels"),
|
||||||
|
# this ruleset can be found under Setup|Service monitoring rules|Various
|
||||||
|
topic=Topic.APPLICATIONS,
|
||||||
|
# define the name of the function which creates the GUI elements
|
||||||
|
parameter_form=_parameter_form,
|
||||||
|
# define the label in the GUI where you can restrict the
|
||||||
|
# settings to one or mor specific users (item)
|
||||||
|
condition=HostAndItemCondition(item_title=Title("Mailbox")),
|
||||||
|
)
|
98
mailcow/rulesets/rs_mailcow_params.py
Normal file
98
mailcow/rulesets/rs_mailcow_params.py
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=line-too-long
|
||||||
|
"""defines the form for typing in all needed HAL9002 parameters"""
|
||||||
|
|
||||||
|
from cmk.rulesets.v1 import Help, Title, Label
|
||||||
|
from cmk.rulesets.v1.form_specs import (
|
||||||
|
DictElement,
|
||||||
|
Dictionary,
|
||||||
|
String,
|
||||||
|
validators,
|
||||||
|
BooleanChoice,
|
||||||
|
Integer,
|
||||||
|
Password,
|
||||||
|
migrate_to_password,
|
||||||
|
InputHint,
|
||||||
|
DefaultValue,
|
||||||
|
)
|
||||||
|
from cmk.rulesets.v1.rule_specs import SpecialAgent, Topic
|
||||||
|
|
||||||
|
|
||||||
|
def _form_spec_special_agent_mailcow() -> Dictionary:
|
||||||
|
return Dictionary(
|
||||||
|
title=Title("Mailcow Server Information"),
|
||||||
|
help_text=Help("Checking Mailcow systems via API"),
|
||||||
|
elements={
|
||||||
|
"hostname": DictElement(
|
||||||
|
required=True,
|
||||||
|
parameter_form=String(
|
||||||
|
title=Title("Hostname"),
|
||||||
|
help_text=Help(
|
||||||
|
"Hostname of Mailcow server (bare FQDN or IP), mandatory, eg. mailcow.yourdomain.tld"
|
||||||
|
),
|
||||||
|
custom_validate=(validators.LengthInRange(min_value=1),),
|
||||||
|
prefill=InputHint("mailcow.yourdomain.tld"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
"apikey": DictElement(
|
||||||
|
required=True,
|
||||||
|
parameter_form=Password(
|
||||||
|
title=Title("API key"),
|
||||||
|
help_text=Help("Specify API key, mandatory"),
|
||||||
|
custom_validate=(validators.LengthInRange(min_value=1),),
|
||||||
|
migrate=migrate_to_password,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
"port": DictElement(
|
||||||
|
required=False,
|
||||||
|
parameter_form=Integer(
|
||||||
|
title=Title("Port"),
|
||||||
|
help_text=Help(
|
||||||
|
"Specify port the Mailcow system ist listening on, mandatory"
|
||||||
|
),
|
||||||
|
prefill=DefaultValue(443),
|
||||||
|
custom_validate=(validators.NetworkPort(),),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
"check_version": DictElement(
|
||||||
|
required=False,
|
||||||
|
parameter_form=BooleanChoice(
|
||||||
|
title=Title("Check Mailcow version"),
|
||||||
|
help_text=Help(
|
||||||
|
"Activate to check version of running Mailcow against actual Github version, optional"
|
||||||
|
),
|
||||||
|
label=Label(
|
||||||
|
"Enable version check (requires access to Github internet site)"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
"no_https": DictElement(
|
||||||
|
required=False,
|
||||||
|
parameter_form=BooleanChoice(
|
||||||
|
title=Title("Disable HTTPS"),
|
||||||
|
help_text=Help(
|
||||||
|
"Activate to disable encryption (not recommended), optional"
|
||||||
|
),
|
||||||
|
label=Label("Disable HTTPS"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
"no_cert_check": DictElement(
|
||||||
|
required=False,
|
||||||
|
parameter_form=BooleanChoice(
|
||||||
|
title=Title("Disable certificate validation"),
|
||||||
|
help_text=Help(
|
||||||
|
"Activate to disable certificate validation (not recommended), optional"
|
||||||
|
),
|
||||||
|
label=Label("Disable certificate validation"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
rule_spec_mailcow = SpecialAgent(
|
||||||
|
name="mailcow",
|
||||||
|
title=Title("Mailcow connection parameters"),
|
||||||
|
topic=Topic.APPLICATIONS,
|
||||||
|
parameter_form=_form_spec_special_agent_mailcow,
|
||||||
|
)
|
Binary file not shown.
48
mailcow/server_side_calls/agent_mailcow.py
Normal file
48
mailcow/server_side_calls/agent_mailcow.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=missing-class-docstring, missing-module-docstring, missing-function-docstring
|
||||||
|
|
||||||
|
from collections.abc import Iterable
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from cmk.server_side_calls.v1 import (
|
||||||
|
HostConfig,
|
||||||
|
Secret,
|
||||||
|
SpecialAgentCommand,
|
||||||
|
SpecialAgentConfig,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MailcowParams(BaseModel):
|
||||||
|
hostname: str | None = None
|
||||||
|
apikey: Secret | None = None
|
||||||
|
port: int | None = None
|
||||||
|
no_https: bool = False
|
||||||
|
no_cert_check: bool = False
|
||||||
|
check_version: bool = False
|
||||||
|
|
||||||
|
|
||||||
|
def agent_mailcow_arguments(
|
||||||
|
params: MailcowParams, _host_config: HostConfig
|
||||||
|
) -> Iterable[SpecialAgentCommand]:
|
||||||
|
command_arguments: list[str | Secret] = []
|
||||||
|
if params.hostname is not None:
|
||||||
|
command_arguments += ["--hostname", params.hostname]
|
||||||
|
if params.apikey is not None:
|
||||||
|
command_arguments += ["--apikey", params.apikey.unsafe()]
|
||||||
|
if params.port is not None:
|
||||||
|
command_arguments += ["--port", str(params.port)]
|
||||||
|
if params.no_https:
|
||||||
|
command_arguments.append("--no-https")
|
||||||
|
if params.no_cert_check:
|
||||||
|
command_arguments.append("--no-cert-check")
|
||||||
|
if params.check_version:
|
||||||
|
command_arguments.append("--check-version")
|
||||||
|
yield SpecialAgentCommand(command_arguments=command_arguments)
|
||||||
|
|
||||||
|
|
||||||
|
special_agent_mailcow = SpecialAgentConfig(
|
||||||
|
name="mailcow",
|
||||||
|
parameter_parser=MailcowParams.model_validate,
|
||||||
|
commands_function=agent_mailcow_arguments,
|
||||||
|
)
|
BIN
mkp/Mailcow-2.1.0.mkp
Normal file
BIN
mkp/Mailcow-2.1.0.mkp
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user