From 2ee28623577399377120fd8315fc15c5f2fffff7 Mon Sep 17 00:00:00 2001 From: crcro Date: Fri, 13 Mar 2020 11:16:03 +0200 Subject: [PATCH] app: mailcow-dockerized postfix stats (#11058) * app-mailcow-dockerized-postfix * fix docs * updated niceCase * test-data * snmprec upload * new test data * new test data --- LibreNMS/Util/StringHelpers.php | 1 + doc/Extensions/Applications.md | 25 ++++ .../mailcow-postfix_domains.inc.php | 51 ++++++++ .../mailcow-postfix_emails.inc.php | 55 ++++++++ .../mailcow-postfix_traffic.inc.php | 49 +++++++ includes/html/pages/apps.inc.php | 5 + .../pages/device/apps/mailcow-postfix.inc.php | 46 +++++++ .../applications/mailcow-postfix.inc.php | 78 +++++++++++ tests/data/linux_mailcow-dockerized-v1.json | 121 ++++++++++++++++++ .../linux_mailcow-dockerized-v1.snmprec | 9 ++ 10 files changed, 440 insertions(+) create mode 100644 includes/html/graphs/application/mailcow-postfix_domains.inc.php create mode 100644 includes/html/graphs/application/mailcow-postfix_emails.inc.php create mode 100644 includes/html/graphs/application/mailcow-postfix_traffic.inc.php create mode 100644 includes/html/pages/device/apps/mailcow-postfix.inc.php create mode 100644 includes/polling/applications/mailcow-postfix.inc.php create mode 100644 tests/data/linux_mailcow-dockerized-v1.json create mode 100644 tests/snmpsim/linux_mailcow-dockerized-v1.snmprec diff --git a/LibreNMS/Util/StringHelpers.php b/LibreNMS/Util/StringHelpers.php index 0191e9f686..9254b1387d 100644 --- a/LibreNMS/Util/StringHelpers.php +++ b/LibreNMS/Util/StringHelpers.php @@ -75,6 +75,7 @@ class StringHelpers 'freeradius' => 'FreeRADIUS', 'pi-hole' => 'pi-hole', 'zfs' => 'ZFS', + 'mailcow-postfix' => 'mailcow-dockerized postfix', ]; return isset($replacements[$string]) ? $replacements[$string] : ucwords(str_replace(['_', '-'], ' ', $string)); diff --git a/doc/Extensions/Applications.md b/doc/Extensions/Applications.md index 14ce07f767..7ab18e65d7 100644 --- a/doc/Extensions/Applications.md +++ b/doc/Extensions/Applications.md @@ -99,6 +99,7 @@ by following the steps under the `SNMP Extend` heading. 1. [FreeRADIUS](#freeradius) - SNMP extend, Agent 1. [Freeswitch](#freeswitch) - SNMP extend, Agent 1. [GPSD](#gpsd) - SNMP extend, Agent +1. [Mailcow-dockerized postfix](#mailcow-dockerized-postfix) - SNMP extend 1. [Mailscanner](#mailscanner) - SNMP extend 1. [Mdadm](#mdadm) - SNMP extend 1. [Memcached](#memcached) - SNMP extend @@ -739,6 +740,30 @@ You may need to configure `$server` or `$port`. Verify it is working by running `/usr/lib/check_mk_agent/local/gpsd` +# mailcow-dockerized postfix + +## SNMP Extend + +1: Download the script into the desired host. + +``` +wget https://github.com/librenms/librenms-agent/master/snmp/mailcow-dockerized-postfix -O /etc/snmp/mailcow-dockerized-postfix +``` + +2: Run `chmod +x /etc/snmp/mailcow-dockerized-postfix` + +3: Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: + +``` +extend mailcow-postfix /etc/snmp/mailcow-dockerized-postfix +``` + +4: Restart snmpd on your host + +The application should be auto-discovered as described at the top of +the page. If it is not, please follow the steps set out under `SNMP +Extend` heading top of page. + # Mailscanner ## SNMP Extend diff --git a/includes/html/graphs/application/mailcow-postfix_domains.inc.php b/includes/html/graphs/application/mailcow-postfix_domains.inc.php new file mode 100644 index 0000000000..b83714b5da --- /dev/null +++ b/includes/html/graphs/application/mailcow-postfix_domains.inc.php @@ -0,0 +1,51 @@ + +*/ + +require 'includes/html/graphs/common.inc.php'; + +$scale_min = 0; +$colours = 'mixed'; +$unit_text = 'Domain(s)'; +$unitlen = 10; +$bigdescrlen = 25; +$smalldescrlen = 25; +$dostack = 0; +$printtotal = 0; +$addarea = 1; +$transparency = 33; +$rrd_filename = rrd_name($device['hostname'], array('app', $app['app_type'], $app['app_id'])); + +$array = array( + 'senders' => array('descr' => 'Sender(s)', 'colour' => '11d3f5',), + 'sendinghostsdomains' => array('descr' => 'Sender domain(s)', 'colour' => '11abf2',), + 'recipients' => array('descr' => 'Recipient(s)', 'colour' => 'f78f19',), + 'recipienthostsdomains' => array('descr' => 'Recipient domain(s)', 'colour' => 'e0001a',), +); + +$i = 0; + +if (rrdtool_check_rrd_exists($rrd_filename)) { + foreach ($array as $ds => $var) { + $rrd_list[$i]['filename'] = $rrd_filename; + $rrd_list[$i]['descr'] = $var['descr']; + $rrd_list[$i]['ds'] = $ds; + $rrd_list[$i]['colour'] = $var['colour']; + $i++; + } +} else { + echo "file missing: $rrd_filename"; +} + +require 'includes/html/graphs/generic_v3_multiline.inc.php'; diff --git a/includes/html/graphs/application/mailcow-postfix_emails.inc.php b/includes/html/graphs/application/mailcow-postfix_emails.inc.php new file mode 100644 index 0000000000..3ac710b225 --- /dev/null +++ b/includes/html/graphs/application/mailcow-postfix_emails.inc.php @@ -0,0 +1,55 @@ + +*/ + +require 'includes/html/graphs/common.inc.php'; + +$scale_min = 0; +$colours = 'mixed'; +$unit_text = 'E-mail(s)'; +$unitlen = 10; +$bigdescrlen = 20; +$smalldescrlen = 20; +$dostack = 0; +$printtotal = 0; +$addarea = 1; +$transparency = 33; +$rrd_filename = rrd_name($device['hostname'], array('app', $app['app_type'], $app['app_id'])); + +$array = array( + 'received' => array('descr' => 'Received', 'colour' => '75a832',), + 'delivered' => array('descr' => 'Delivered', 'colour' => '00d644',), + 'forwarded' => array('descr' => 'Forwarded', 'colour' => 'ccff99',), + 'deferred' => array('descr' => 'Deferred', 'colour' => 'ffcc66',), + 'bounced' => array('descr' => 'Bounced', 'colour' => 'cc6600',), + 'rejected' => array('descr' => 'Rejected', 'colour' => 'cc0000',), + 'held' => array('descr' => 'Held', 'colour' => '3366cc',), + 'discarded' => array('descr' => 'Discarded', 'colour' => '1a1a1a',), +); + +$i = 0; + +if (rrdtool_check_rrd_exists($rrd_filename)) { + foreach ($array as $ds => $var) { + $rrd_list[$i]['filename'] = $rrd_filename; + $rrd_list[$i]['descr'] = $var['descr']; + $rrd_list[$i]['ds'] = $ds; + $rrd_list[$i]['colour'] = $var['colour']; + $i++; + } +} else { + echo "file missing: $rrd_filename"; +} + +require 'includes/html/graphs/generic_v3_multiline.inc.php'; diff --git a/includes/html/graphs/application/mailcow-postfix_traffic.inc.php b/includes/html/graphs/application/mailcow-postfix_traffic.inc.php new file mode 100644 index 0000000000..e911ccfc2a --- /dev/null +++ b/includes/html/graphs/application/mailcow-postfix_traffic.inc.php @@ -0,0 +1,49 @@ + +*/ + +require 'includes/html/graphs/common.inc.php'; + +$scale_min = 0; +$colours = 'mixed'; +$unit_text = 'Traffic'; +$unitlen = 15; +$bigdescrlen = 25; +$smalldescrlen = 25; +$dostack = 0; +$printtotal = 0; +$addarea = 1; +$transparency = 33; +$rrd_filename = rrd_name($device['hostname'], array('app', $app['app_type'], $app['app_id'])); + +$array = array( + 'bytesreceived' => array('descr' => 'bytes Received', 'colour' => '4CB24C',), + 'bytesdelivered' => array('descr' => 'bytes Delivered', 'colour' => 'BF3F3F',), +); + +$i = 0; + +if (rrdtool_check_rrd_exists($rrd_filename)) { + foreach ($array as $ds => $var) { + $rrd_list[$i]['filename'] = $rrd_filename; + $rrd_list[$i]['descr'] = $var['descr']; + $rrd_list[$i]['ds'] = $ds; + $rrd_list[$i]['colour'] = $var['colour']; + $i++; + } +} else { + echo "file missing: $rrd_filename"; +} + +require 'includes/html/graphs/generic_v3_multiline.inc.php'; diff --git a/includes/html/pages/apps.inc.php b/includes/html/pages/apps.inc.php index 1771428c6d..8c5c98290e 100644 --- a/includes/html/pages/apps.inc.php +++ b/includes/html/pages/apps.inc.php @@ -315,6 +315,11 @@ $graphs['asterisk'] = array( 'sip', 'iax2', ); +$graphs['mailcow-postfix'] = array( + 'emails', + 'traffic', + 'domains', +); echo '
'; echo '
'; echo "Apps » "; diff --git a/includes/html/pages/device/apps/mailcow-postfix.inc.php b/includes/html/pages/device/apps/mailcow-postfix.inc.php new file mode 100644 index 0000000000..3ccf008519 --- /dev/null +++ b/includes/html/pages/device/apps/mailcow-postfix.inc.php @@ -0,0 +1,46 @@ +. +* +* @package LibreNMS +* @link http://librenms.org +* @copyright 2020 LibreNMS +* @author Cercel Valentin +*/ + +$graphs = array( + 'mailcow-postfix_emails' => 'E-mail(s)', + 'mailcow-postfix_traffic' => 'Traffic', + 'mailcow-postfix_domains' => 'Domain(s)', +); + +foreach ($graphs as $key => $text) { + $graph_type = $key; + $graph_array['height'] = '100'; + $graph_array['width'] = '215'; + $graph_array['to'] = \LibreNMS\Config::get('time.now'); + $graph_array['id'] = $app['app_id']; + $graph_array['type'] = 'application_' . $key; + + echo '
+
+

' . $text . '

+
+
+
'; + include 'includes/html/print-graphrow.inc.php'; + echo '
'; + echo '
'; + echo '
'; +} diff --git a/includes/polling/applications/mailcow-postfix.inc.php b/includes/polling/applications/mailcow-postfix.inc.php new file mode 100644 index 0000000000..094fa80b0c --- /dev/null +++ b/includes/polling/applications/mailcow-postfix.inc.php @@ -0,0 +1,78 @@ +. +* +* @package LibreNMS +* @link http://librenms.org +* @copyright 2020 LibreNMS +* @author Cercel Valentin +*/ + +use LibreNMS\Exceptions\JsonAppException; +use LibreNMS\RRD\RrdDefinition; + +$name = 'mailcow-postfix'; +$app_id = $app['app_id']; + +d_echo($name); + +try { + $mailcow_postfix = json_app_get($device, $name); +} catch (JsonAppException $e) { + echo PHP_EOL . $name . ':' . $e->getCode() . ':' . $e->getMessage() . PHP_EOL; + update_application($app, $e->getCode() . ':' . $e->getMessage(), []); // Set empty metrics and error message + return; +} + +$rrd_name = array('app', $name, $app_id); + +$rrd_def = RrdDefinition::make() + ->addDataset('received', 'GAUGE', 0) + ->addDataset('delivered', 'GAUGE', 0) + ->addDataset('forwarded', 'GAUGE', 0) + ->addDataset('deferred', 'GAUGE', 0) + ->addDataset('bounced', 'GAUGE', 0) + ->addDataset('rejected', 'GAUGE', 0) + ->addDataset('rejectwarnings', 'GAUGE', 0) + ->addDataset('held', 'GAUGE', 0) + ->addDataset('discarded', 'GAUGE', 0) + ->addDataset('bytesreceived', 'GAUGE', 0) + ->addDataset('bytesdelivered', 'GAUGE', 0) + ->addDataset('senders', 'GAUGE', 0) + ->addDataset('sendinghostsdomains', 'GAUGE', 0) + ->addDataset('recipients', 'GAUGE', 0) + ->addDataset('recipienthostsdomains', 'GAUGE', 0); + + +$fields = array( + 'received' => $mailcow_postfix['data']['received'], + 'delivered' => $mailcow_postfix['data']['delivered'], + 'forwarded' => $mailcow_postfix['data']['forwarded'], + 'deferred' => $mailcow_postfix['data']['deferred'], + 'bounced' => $mailcow_postfix['data']['bounced'], + 'rejected' => $mailcow_postfix['data']['rejected'], + 'rejectwarnings' => $mailcow_postfix['data']['rejectwarnings'], + 'held' => $mailcow_postfix['data']['held'], + 'discarded' => $mailcow_postfix['data']['discarded'], + 'bytesreceived' => $mailcow_postfix['data']['bytesreceived'], + 'bytesdelivered' => $mailcow_postfix['data']['bytesdelivered'], + 'senders' => $mailcow_postfix['data']['senders'], + 'sendinghostsdomains' => $mailcow_postfix['data']['sendinghostsdomains'], + 'recipients' => $mailcow_postfix['data']['recipients'], + 'recipienthostsdomains' => $mailcow_postfix['data']['recipienthostsdomains'], +); + +$tags = compact('name', 'app_id', 'rrd_name', 'rrd_def'); +data_update($device, 'app', $tags, $fields); +update_application($app, 'OK', $fields); diff --git a/tests/data/linux_mailcow-dockerized-v1.json b/tests/data/linux_mailcow-dockerized-v1.json new file mode 100644 index 0000000000..aabf1b753b --- /dev/null +++ b/tests/data/linux_mailcow-dockerized-v1.json @@ -0,0 +1,121 @@ +{ + "applications": { + "discovery": { + "applications": [ + { + "app_type": "mailcow-postfix", + "app_state": "UNKNOWN", + "discovered": 1, + "app_state_prev": null, + "app_status": "", + "app_instance": "" + } + ], + "application_metrics": [] + }, + "poller": { + "applications": [ + { + "app_type": "mailcow-postfix", + "app_state": "OK", + "discovered": 1, + "app_state_prev": "UNKNOWN", + "app_status": "", + "app_instance": "" + } + ], + "application_metrics": [ + { + "metric": "bounced", + "value": 0, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "bytesdelivered", + "value": 128364, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "bytesreceived", + "value": 64182, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "deferred", + "value": 0, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "delivered", + "value": 4, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "discarded", + "value": 0, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "forwarded", + "value": 0, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "held", + "value": 0, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "received", + "value": 2, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "recipienthostsdomains", + "value": 2, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "recipients", + "value": 2, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "rejected", + "value": 0, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "rejectwarnings", + "value": 0, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "senders", + "value": 2, + "value_prev": null, + "app_type": "mailcow-postfix" + }, + { + "metric": "sendinghostsdomains", + "value": 2, + "value_prev": null, + "app_type": "mailcow-postfix" + } + ] + } + } +} diff --git a/tests/snmpsim/linux_mailcow-dockerized-v1.snmprec b/tests/snmpsim/linux_mailcow-dockerized-v1.snmprec new file mode 100644 index 0000000000..41f72c0cac --- /dev/null +++ b/tests/snmpsim/linux_mailcow-dockerized-v1.snmprec @@ -0,0 +1,9 @@ +1.3.6.1.2.1.1.1.0|4|Linux mbx01 4.15.0-88-generic #88-Ubuntu SMP Tue Feb 11 20:11:34 UTC 2020 x86_64 +1.3.6.1.2.1.1.2.0|6|1.3.6.1.4.1.8072.3.2.10 +1.3.6.1.2.1.1.3.0|67|43985546 +1.3.6.1.2.1.1.4.0|4| +1.3.6.1.2.1.1.5.0|4| +1.3.6.1.2.1.1.6.0|4| +1.3.6.1.2.1.25.1.1.0|67|43989477 +1.3.6.1.4.1.8072.1.3.2.2.1.21.15.109.97.105.108.99.111.119.45.112.111.115.116.102.105.120|2|1 +1.3.6.1.4.1.8072.1.3.2.3.1.2.15.109.97.105.108.99.111.119.45.112.111.115.116.102.105.120|4|{"data":{"received":"2","delivered":"4","forwarded":"0","deferred":"0","bounced":"0","rejected":"0","rejectwarnings":"0","held":"0","discarded":"0","bytesreceived":"64182","bytesdelivered":"128364","senders":"2","sendinghostsdomains":"2","recipients":"2","recipienthostsdomains":"2"},"error":"0","errorString":"","version":"1"}