217 lines
8.0 KiB
Python
217 lines
8.0 KiB
Python
#!/usr/bin/env python3
|
|
# pylint: disable=too-many-locals, line-too-long, too-many-statements, too-many-branches
|
|
"""Mailcow check for mailboxes"""
|
|
|
|
import time
|
|
from pprint import pprint
|
|
|
|
from cmk.utils import debug
|
|
|
|
# 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
|
|
if debug.enabled():
|
|
pprint(section)
|
|
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",
|
|
)
|