Last active
April 11, 2019 19:49
-
-
Save PhrozenByte/2f11fef03dc0380be19c to your computer and use it in GitHub Desktop.
Munin plugins for ViMbAdmin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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']); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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