Skip to content

Instantly share code, notes, and snippets.

@PhrozenByte
Last active April 11, 2019 19:49
Show Gist options
  • Save PhrozenByte/2f11fef03dc0380be19c to your computer and use it in GitHub Desktop.
Save PhrozenByte/2f11fef03dc0380be19c to your computer and use it in GitHub Desktop.
Munin plugins for ViMbAdmin
#!/usr/bin/env php
<?php
/**
* ViMbAdmin munin plugin
* Version 2.4 (build 20190411)
*
* SHORT DESCRIPTION:
* Monitors the number of domains, mailboxes and aliases.
*
* DEPENDENCIES:
* This plugin requires various helper functions. You can download the
* required plugin.php from http://daniel-rudolf.de/oss/munin-php-helper
*
* COPYRIGHT AND LICENSING:
* Copyright (C) 2014-2019 Daniel Rudolf <www.daniel-rudolf.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* See <http://www.gnu.org/licenses/> to receive a full-text-copy of
* the GNU General Public License.
*/
if (!file_exists(__DIR__ . '/plugin.php')) {
print_stderr('Unable to include helper functions from \'' . __DIR__ . '/plugin.php' .'\': No such file or directory');
print_stderr('You will need to download PhrozenByte\'s PHP helper functions from http://daniel-rudolf.de/oss/munin-php-helper');
exit(1);
}
require_once(__DIR__ . '/plugin.php');
define('GRAPH_NAME', 'vimbadmin_count');
// read munin plugin config
define('DATABASE_DSN', isset($_SERVER['database_dsn']) ? $_SERVER['database_dsn'] : 'mysql:host=localhost;port=3306;dbname=vimbadmin;charset=utf8');
define('DATABASE_USER', isset($_SERVER['database_user']) ? $_SERVER['database_user'] : 'root');
define('DATABASE_PASSWORD', isset($_SERVER['database_password']) ? $_SERVER['database_password'] : '');
// alias and mailbox count: percent of defined maximum
// domain count: absolute value
define('WARNING', isset($_SERVER['warning']) ? (float) $_SERVER['warning'] : 0.8);
define('CRITICAL', isset($_SERVER['critical']) ? (float) $_SERVER['critical'] : 1.0);
// check multigraph capability
if (!check_multigraph(true)) {
exit(0);
}
// connect to database
try {
$pdo = new PDO(DATABASE_DSN, DATABASE_USER, DATABASE_PASSWORD, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
} catch(PDOException $e) {
if (is_munin_autoconf()) {
print_stdout('no (unable to connect to database)');
exit(0);
}
print_stderr('Unable to connect to database: ' . $e->getMessage());
exit(1);
}
// read domains from database
try {
$domains = $pdo->query('
SELECT id, domain, max_aliases, alias_count, max_mailboxes, mailbox_count
FROM domain
ORDER BY id ASC
')->fetchAll(PDO::FETCH_ASSOC);
} catch(PDOException $e) {
if (is_munin_autoconf()) {
print_stdout('no (unable to read domains from database)');
exit(0);
}
print_stderr('Unable to read domains from database: ' . $e->getMessage());
exit(1);
}
// autoconf: everything seems to be fine...
if (is_munin_autoconf()) {
print_stdout("yes");
exit(0);
}
/**
* print graph configs
*/
if (is_munin_config()) {
$currentDomain = null;
do {
// graph config
if ($currentDomain === null) {
print_stdout('multigraph ' . GRAPH_NAME);
print_stdout('graph_title ViMbAdmin');
print_stdout('graph_info This graph shows the number of domains, mailboxes and aliases managed by ViMbAdmin.');
print_stdout('graph_order domain mailbox alias');
} else {
print_stdout('multigraph ' . GRAPH_NAME . '.' . GRAPH_NAME . '_d' . $currentDomain['id']);
print_stdout('graph_title ViMbAdmin domain statistics for domain "' . $currentDomain['domain'] . '"');
print_stdout('graph_info This graph shows the number of mailboxes and aliases of domain "' . $currentDomain['domain'] . '".');
print_stdout('graph_order mailbox alias');
}
print_stdout('graph_vlabel count');
print_stdout('graph_category mail');
print_stdout('graph_args --lower-limit 0');
// domain line
if ($currentDomain === null) {
print_stdout('domain.label Domains');
print_stdout('domain.info Number of domains.');
print_stdout('domain.type GAUGE');
print_stdout('domain.min 0');
$warning = get_multigraph_env('domain', 'warning');
if ($warning !== null) {
print_stdout('domain.warning ' . $warning);
}
$critical = get_multigraph_env('domain', 'critical');
if ($critical !== null) {
print_stdout('domain.critical ' . $critical);
}
}
// mailbox line
print_stdout('mailbox.label Mailboxes');
print_stdout('mailbox.info Number of mailboxes.');
print_stdout('mailbox.type GAUGE');
print_stdout('mailbox.min 0');
if (($currentDomain !== null) && ($currentDomain['max_mailboxes'] > 0)) {
$warning = get_multigraph_env('mailbox', 'warning', 'd' . $currentDomain['id']);
$warning = ($warning !== null) ? $warning : WARNING;
print_stdout('mailbox.warning ' . (int) round($currentDomain['max_mailboxes'] * $warning));
$critical = get_multigraph_env('mailbox', 'critical', 'd' . $currentDomain['id']);
$critical = ($critical !== null) ? $critical : CRITICAL;
print_stdout('mailbox.critical ' . (int) round($currentDomain['max_mailboxes'] * $critical));
}
// alias line
print_stdout('alias.label Aliases');
print_stdout('alias.info Number of aliases.');
print_stdout('alias.type GAUGE');
print_stdout('alias.min 0');
if (($currentDomain !== null) && ($currentDomain['max_aliases'] != 0)) {
$warning = get_multigraph_env('alias', 'warning', 'd' . $currentDomain['id']);
$warning = ($warning !== null) ? $warning : WARNING;
print_stdout('alias.warning ' . (int) round($currentDomain['max_aliases'] * $warning));
$critical = get_multigraph_env('alias', 'critical', 'd' . $currentDomain['id']);
$critical = ($critical !== null) ? $critical : CRITICAL;
print_stdout('alias.critical ' . (int) round($currentDomain['max_aliases'] * $critical));
}
// first iteration is the root graph, all following iterations are domain graphs
$nextDomainData = each($domains);
$currentDomain = ($nextDomainData !== false) ? $nextDomainData['value'] : false;
} while ($currentDomain !== false);
exit(0);
}
/**
* print graph data
*/
// edit data and calculate totals
$total = array();
$total['mailbox_count'] = $total['alias_count'] = $total['domain_count'] = 0;
foreach ($domains as &$domain) {
$domain['max_aliases'] = intval($domain['max_aliases']);
$domain['alias_count'] = intval($domain['alias_count']);
$domain['max_mailboxes'] = intval($domain['max_mailboxes']);
$domain['mailbox_count'] = intval($domain['mailbox_count']);
$total['mailbox_count'] += $domain['mailbox_count'];
$total['alias_count'] += $domain['alias_count'];
$total['domain_count']++;
}
unset($domain);
// print root graph
print_stdout('multigraph ' . GRAPH_NAME);
print_stdout('domain.value ' . $total['domain_count']);
print_stdout('mailbox.value ' . $total['mailbox_count']);
print_stdout('alias.value ' . $total['alias_count']);
// print domain graphs
foreach ($domains as $domain) {
print_stdout('multigraph ' . GRAPH_NAME . '.' . GRAPH_NAME . '_d' . $domain['id']);
print_stdout('mailbox.value ' . $domain['mailbox_count']);
print_stdout('alias.value ' . $domain['alias_count']);
}
#!/usr/bin/env php
<?php
/**
* ViMbAdmin munin plugin
* Version 2.4 (build 20190411)
*
* SHORT DESCRIPTION:
* Monitors the quota of domains and mailboxes.
*
* DEPENDENCIES:
* This plugin requires various helper functions. You can download the
* required plugin.php from http://daniel-rudolf.de/oss/munin-php-helper
*
* COPYRIGHT AND LICENSING:
* Copyright (C) 2014-2019 Daniel Rudolf <www.daniel-rudolf.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* See <http://www.gnu.org/licenses/> to receive a full-text-copy of
* the GNU General Public License.
*/
if (!file_exists(__DIR__ . '/plugin.php')) {
print_stderr('Unable to include helper functions from \'' . __DIR__ . '/plugin.php' .'\': No such file or directory');
print_stderr('You will need to download PhrozenByte\'s PHP helper functions from http://daniel-rudolf.de/oss/munin-php-helper');
exit(1);
}
require_once(__DIR__ . '/plugin.php');
define('GRAPH_NAME', 'vimbadmin_sizes');
// read munin plugin config
define('DATABASE_DSN', isset($_SERVER['database_dsn']) ? $_SERVER['database_dsn'] : 'mysql:host=localhost;port=3306;dbname=vimbadmin;charset=utf8');
define('DATABASE_USER', isset($_SERVER['database_user']) ? $_SERVER['database_user'] : 'root');
define('DATABASE_PASSWORD', isset($_SERVER['database_password']) ? $_SERVER['database_password'] : '');
// maildir: percent of defined quota
// homedir: absolute value (bytes)
define('WARNING', isset($_SERVER['warning']) ? (float) $_SERVER['warning'] : 0.8);
define('CRITICAL', isset($_SERVER['critical']) ? (float) $_SERVER['critical'] : 1.0);
if (isset($_SERVER['measured_line'])) {
if ($_SERVER['measured_line'] == 'force-no') {
// hide measured line, even those in the past (removes the field)
define('MEASURED_LINE', false);
} elseif ($_SERVER['measured_line'] == 'yes') {
// draw measured lines
define('MEASURED_LINE', true);
} else {
// hide future measured lines (stops collecting the state)
define('MEASURED_LINE', null);
}
} else {
define('MEASURED_LINE', true);
}
// check multigraph capability
if (!check_multigraph(true)) {
exit(0);
}
// connect to database
try {
$pdo = new PDO(DATABASE_DSN, DATABASE_USER, DATABASE_PASSWORD, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
} catch(PDOException $e) {
if (is_munin_autoconf()) {
print_stdout('no (unable to connect to database)');
exit(0);
}
print_stderr('Unable to connect to database: ' . $e->getMessage());
exit(1);
}
// read data from database
try {
// read domains
$domains = $pdo->query('
SELECT id, domain, max_quota
FROM domain
ORDER BY id ASC
')->fetchAll(PDO::FETCH_ASSOC);
// read mailboxes and group them by domain
$mailboxes = $pdo->query('
SELECT Domain_id, id, username, quota, homedir_size, maildir_size, UNIX_TIMESTAMP(size_at) AS size_at
FROM mailbox
ORDER BY Domain_id ASC, id ASC
')->fetchAll(PDO::FETCH_ASSOC | PDO::FETCH_GROUP);
} catch(PDOException $e) {
if (is_munin_autoconf()) {
print_stdout('no (invalid database)');
exit(0);
}
print_stderr('Unable to read from database: ' . $e->getMessage());
exit(1);
}
// autoconf: everything seems to be fine...
if (is_munin_autoconf()) {
print_stdout("yes");
exit(0);
}
// edit data and calculate domain sums and totals
$total = array();
$total['size_at'] = TIME_NOW;
$total['maildir_size'] = $total['homedir_size'] = 0;
foreach ($domains as &$domain) {
$domain['size_at'] = TIME_NOW;
$domain['maildir_size'] = $domain['homedir_size'] = 0;
// edit domain data
$domain['max_quota'] = intval($domain['max_quota']);
// walk through the mailboxes of this domain
if (isset($mailboxes[$domain['id']])) {
foreach ($mailboxes[$domain['id']] as &$mailbox) {
if (!$mailbox['size_at']) {
$mailbox['size_at'] = TIME_NOW;
}
// edit mailbox data
$mailbox['quota'] = intval($mailbox['quota']);
$mailbox['homedir_size'] = intval($mailbox['homedir_size']);
$mailbox['maildir_size'] = intval($mailbox['maildir_size']);
$mailbox['size_at'] = intval($mailbox['size_at']);
// calculate domain sum
$domain['size_at'] = min($domain['size_at'], $mailbox['size_at']);
$domain['maildir_size'] += $mailbox['maildir_size'];
$domain['homedir_size'] += $mailbox['homedir_size'];
}
unset($mailbox);
}
// calculate total
$total['size_at'] = min($total['size_at'], $domain['size_at']);
$total['maildir_size'] += $domain['maildir_size'];
$total['homedir_size'] += $domain['homedir_size'];
}
unset($domain);
/**
* print graph configs
*/
if (is_munin_config()) {
reset($domains);
$currentDomain = null;
do {
$currentMailbox = null;
do {
// graph config
if ($currentDomain === null) {
print_stdout('multigraph ' . GRAPH_NAME);
print_stdout('graph_title ViMbAdmin mailbox sizes');
print_stdout('graph_info This graph shows the total size of mailboxes managed by ViMbAdmin.');
} elseif ($currentMailbox === null) {
print_stdout('multigraph ' . GRAPH_NAME . '.' . GRAPH_NAME . '_d' . $currentDomain['id']);
print_stdout('graph_title ViMbAdmin mailbox sizes of domain "' . $currentDomain['domain'] . '"');
print_stdout('graph_info This graph shows the total size of mailboxes at "' . $currentDomain['domain'] . '".');
} else {
print_stdout('multigraph ' . GRAPH_NAME . '.' . GRAPH_NAME . '_d' . $currentDomain['id'] . '.' . GRAPH_NAME . '_d' . $currentDomain['id'] . '_m' . $currentMailbox['id']);
print_stdout('graph_title ViMbAdmin mailbox size of "' . $currentMailbox['username'] . '"');
print_stdout('graph_info This graph shows the size of mailbox "' . $currentMailbox['username'] . '".');
}
print_stdout('graph_args --base 1024 --lower-limit 0');
print_stdout('graph_vlabel bytes');
print_stdout('graph_category mail');
print_stdout('graph_order maildir homedir' . ((MEASURED_LINE !== false) ? ' measured' : ''));
// maildir area
print_stdout('maildir.label Mail directory size');
print_stdout('maildir.info Size of the mail directory in bytes.');
print_stdout('maildir.type GAUGE');
print_stdout('maildir.draw AREA');
print_stdout('maildir.min 0');
// maildir = if (maildir == UN) { PREV } else { maildir }
print_stdout('maildir.cdef maildir,UN,PREV,maildir,IF');
if ($currentMailbox !== null) {
if ($currentMailbox['quota'] > 0) {
$warning = get_multigraph_env('maildir', 'warning', 'd' . $currentDomain['id'], 'm' . $currentMailbox['id']);
$warning = ($warning !== null) ? $warning : WARNING;
print_stdout('maildir.warning ' . (int) round($currentMailbox['quota'] * $warning));
$critical = get_multigraph_env('maildir', 'critical', 'd' . $currentDomain['id'], 'm' . $currentMailbox['id']);
$critical = ($critical !== null) ? $critical : CRITICAL;
print_stdout('maildir.critical ' . (int) round($currentMailbox['quota'] * $critical));
}
} elseif ($currentDomain !== null) {
if ($currentDomain['max_quota'] > 0) {
$warning = get_multigraph_env('maildir', 'warning', 'd' . $currentDomain['id']);
$warning = ($warning !== null) ? $warning : WARNING;
print_stdout('maildir.warning ' . (int) round($currentDomain['max_quota'] * $warning));
$critical = get_multigraph_env('maildir', 'critical', 'd' . $currentDomain['id']);
$critical = ($critical !== null) ? $critical : CRITICAL;
print_stdout('maildir.critical ' . (int) round($currentDomain['max_quota'] * $critical));
}
}
// homedir area
print_stdout('homedir.label Home directory size');
print_stdout('homedir.info Size of the home directory in bytes.');
print_stdout('homedir.type GAUGE');
print_stdout('homedir.draw LINE2');
print_stdout('homedir.min 0');
// homedir = if (homedir == UN) { PREV } else { homedir }
print_stdout('homedir.cdef homedir,UN,PREV,homedir,IF');
$warning = get_multigraph_env('homedir', 'warning');
if ($warning !== null) {
print_stdout('homedir.warning ' . $warning);
}
$critical = get_multigraph_env('homedir', 'critical');
if ($critical !== null) {
print_stdout('homedir.critical ' . $critical);
}
// measured line
if (MEASURED_LINE !== false) {
print_stdout('measured.label Measured value');
print_stdout('measured.info Draws a vertical line where values were measured and not filled up');
print_stdout('measured.type GAUGE');
print_stdout('measured.draw STACK');
print_stdout('measured.colour 000000');
print_stdout('measured.cdef measured,UN,UNKN,INF,IF'); // measured = if ( measured == UN ) { UNKN } else { INF }
}
// if this is a domain graph, iterate over its mailboxes
$currentMailbox = false;
if (($currentDomain !== null) && isset($mailboxes[$currentDomain['id']])) {
$nextMailboxData = each($mailboxes[$currentDomain['id']]);
$currentMailbox = ($nextMailboxData !== false) ? $nextMailboxData['value'] : false;
}
} while ($currentMailbox !== false);
// first iteration is the root graph, all following iterations are domain graphs
$nextDomainData = each($domains);
if ($nextDomainData !== false) {
$currentDomain = $nextDomainData['value'];
if (isset($mailboxes[$currentDomain['id']])) {
reset($mailboxes[$currentDomain['id']]);
}
} else {
$currentDomain = false;
}
} while ($currentDomain !== false);
exit(0);
}
/**
* print graph data
*/
$stateData = read_statefile();
$saveStateData = array();
// calculate and print values
reset($domains);
$currentDomain = null;
do {
$currentMailbox = null;
do {
// determine to-be-used identifier and data
if ($currentDomain === null) {
$identifier = GRAPH_NAME;
$fullIdentifier = GRAPH_NAME;
$data = $total;
} elseif ($currentMailbox === null) {
$identifier = GRAPH_NAME . '_d' . $currentDomain['id'];
$fullIdentifier = GRAPH_NAME . '.' . GRAPH_NAME . '_d' . $currentDomain['id'];
$data = $currentDomain;
} else {
$identifier = GRAPH_NAME . '_d' . $currentDomain['id'] . '_m' . $currentMailbox['id'];
$fullIdentifier = GRAPH_NAME . '.' . GRAPH_NAME . '_d' . $currentDomain['id'] . '.' . GRAPH_NAME . '_d' . $currentDomain['id'] . '_m' . $currentMailbox['id'];
$data = $currentMailbox;
}
// save values to statefile
$saveStateData[$identifier]['sizeAt'] = $data['size_at'];
$saveStateData[$identifier]['maildirSize'] = $data['maildir_size'];
$saveStateData[$identifier]['homedirSize'] = $data['homedir_size'];
// print values
print_stdout('multigraph ' . $fullIdentifier);
if (!isset($stateData[$identifier]['sizeAt']) || ($data['size_at'] > $stateData[$identifier]['sizeAt'])) {
$timePrefix = ($data['size_at'] !== TIME_NOW) ? $data['size_at'] . ':' : '';
print_stdout('maildir.value ' . $timePrefix . $data['maildir_size']);
print_stdout('homedir.value ' . $timePrefix . $data['homedir_size']);
if (MEASURED_LINE !== false) {
// even a mailbox without any messages can't have a homedir_size of 0 bytes,
// because at least the "physical" directory on the filesystem occupies 4 kB
// if maildir_size and homedir_size both have a size of 0 bytes,
// the mailbox wasn't initialized at all
if ((MEASURED_LINE === null) || (($data['maildir_size'] === 0) && ($data['homedir_size'] === 0))) {
print_stdout('measured.value ' . $timePrefix . 'U');
} else {
print_stdout('measured.value ' . $timePrefix . '1');
}
}
} elseif (isset($stateData[$identifier]['maildirSize']) && isset($stateData[$identifier]['homedirSize'])) {
print_stdout('maildir.value ' . $stateData[$identifier]['maildirSize']);
print_stdout('homedir.value ' . $stateData[$identifier]['homedirSize']);
if (MEASURED_LINE !== false) {
print_stdout('measured.value U');
}
} else {
print_stdout('maildir.value U');
print_stdout('homedir.value U');
if (MEASURED_LINE !== false) {
print_stdout('measured.value U');
}
}
// if this is a domain graph, iterate over its mailboxes
$currentMailbox = false;
if (($currentDomain !== null) && isset($mailboxes[$currentDomain['id']])) {
$nextMailboxData = each($mailboxes[$currentDomain['id']]);
$currentMailbox = ($nextMailboxData !== false) ? $nextMailboxData['value'] : false;
}
} while ($currentMailbox !== false);
// first iteration is the root graph, all following iterations are domain graphs
$nextDomainData = each($domains);
if ($nextDomainData !== false) {
$currentDomain = $nextDomainData['value'];
if (isset($mailboxes[$currentDomain['id']])) {
reset($mailboxes[$currentDomain['id']]);
}
} else {
$currentDomain = false;
}
} while ($currentDomain !== false);
// update statefile
write_statefile($saveStateData);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment