From 3919ff400d83dd3fc82bf7468c77c4119171ac63 Mon Sep 17 00:00:00 2001 From: reachableceo Date: Thu, 30 Jul 2026 12:16:07 -0500 Subject: [PATCH] feat(oam): add LibreNMS/check_mk monitoring agent role MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Port Modules/OAM/oam-librenms.sh. Deploys the check_mk agent and systemd socket for LibreNMS monitoring, along with the local plugins: distro, dmi, dpkg, ntp-client, os-updates, postfixdetailed, and postfix-queues. 🤖 Generated with [Crush](https://github.com/charmassociates/crush) Assisted-by: GLM-5 via Crush --- roles/oam/files/librenms/check_mk.socket | 9 + roles/oam/files/librenms/check_mk@.service | 7 + roles/oam/files/librenms/check_mk_agent | 659 +++++++++++++++++++++ roles/oam/files/librenms/distro | 114 ++++ roles/oam/files/librenms/dmi.sh | 9 + roles/oam/files/librenms/dpkg.sh | 22 + roles/oam/files/librenms/ntp-client | 34 ++ roles/oam/files/librenms/os-updates.sh | 73 +++ roles/oam/files/librenms/postfix-queues | 13 + roles/oam/files/librenms/postfixdetailed | 548 +++++++++++++++++ roles/oam/handlers/main.yml | 7 + roles/oam/tasks/main.yml | 57 ++ 12 files changed, 1552 insertions(+) create mode 100644 roles/oam/files/librenms/check_mk.socket create mode 100644 roles/oam/files/librenms/check_mk@.service create mode 100644 roles/oam/files/librenms/check_mk_agent create mode 100644 roles/oam/files/librenms/distro create mode 100644 roles/oam/files/librenms/dmi.sh create mode 100644 roles/oam/files/librenms/dpkg.sh create mode 100644 roles/oam/files/librenms/ntp-client create mode 100644 roles/oam/files/librenms/os-updates.sh create mode 100644 roles/oam/files/librenms/postfix-queues create mode 100644 roles/oam/files/librenms/postfixdetailed create mode 100644 roles/oam/handlers/main.yml create mode 100644 roles/oam/tasks/main.yml diff --git a/roles/oam/files/librenms/check_mk.socket b/roles/oam/files/librenms/check_mk.socket new file mode 100644 index 0000000..02760ff --- /dev/null +++ b/roles/oam/files/librenms/check_mk.socket @@ -0,0 +1,9 @@ +[Unit] +Description=Check_MK LibreNMS Agent Socket + +[Socket] +ListenStream=6556 +Accept=yes + +[Install] +WantedBy=sockets.target diff --git a/roles/oam/files/librenms/check_mk@.service b/roles/oam/files/librenms/check_mk@.service new file mode 100644 index 0000000..bea7144 --- /dev/null +++ b/roles/oam/files/librenms/check_mk@.service @@ -0,0 +1,7 @@ +[Unit] +Description=Check_MK LibreNMS Agent Service +After=network.target + +[Service] +ExecStart=/usr/bin/check_mk_agent +StandardOutput=socket diff --git a/roles/oam/files/librenms/check_mk_agent b/roles/oam/files/librenms/check_mk_agent new file mode 100644 index 0000000..6b6e03a --- /dev/null +++ b/roles/oam/files/librenms/check_mk_agent @@ -0,0 +1,659 @@ +#!/bin/bash +# +------------------------------------------------------------------+ +# | ____ _ _ __ __ _ __ | +# | / ___| |__ ___ ___| | __ | \/ | |/ / | +# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / | +# | | |___| | | | __/ (__| < | | | | . \ | +# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ | +# | | +# | Copyright Mathias Kettner 2014 mk@mathias-kettner.de | +# +------------------------------------------------------------------+ +# +# This file is part of Check_MK. +# The official homepage is at http://mathias-kettner.de/check_mk. +# +# check_mk 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 in version 2. check_mk is distributed +# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with- +# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU General Public License for more de- +# ails. You should have received a copy of the GNU General Public +# License along with GNU Make; see the file COPYING. If not, write +# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +# Boston, MA 02110-1301 USA. + +# Remove locale settings to eliminate localized outputs where possible +export LC_ALL=C +unset LANG + +export MK_LIBDIR="/usr/lib/check_mk_agent" +export MK_CONFDIR="/etc/check_mk" +export MK_VARDIR="/var/lib/check_mk_agent" + +# Provide information about the remote host. That helps when data +# is being sent only once to each remote host. +if [ "$REMOTE_HOST" ] ; then + export REMOTE=$REMOTE_HOST +elif [ "$SSH_CLIENT" ] ; then + export REMOTE=${SSH_CLIENT%% *} +fi + +# Make sure, locally installed binaries are found +PATH=$PATH:/usr/local/bin + +# All executables in PLUGINSDIR will simply be executed and their +# ouput appended to the output of the agent. Plugins define their own +# sections and must output headers with '<<<' and '>>>' +PLUGINSDIR=$MK_LIBDIR/plugins + +# All executables in LOCALDIR will by executabled and their +# output inserted into the section <<>>. Please +# refer to online documentation for details about local checks. +LOCALDIR=$MK_LIBDIR/local + +# All files in SPOOLDIR will simply appended to the agent +# output if they are not outdated (see below) +SPOOLDIR=$MK_VARDIR/spool + +# close standard input (for security reasons) and stderr +if [ "$1" = -d ] +then + set -xv +else + exec /dev/null +fi + +# Runs a command asynchronous by use of a cache file +function run_cached () { + local section= + if [ "$1" = -s ] ; then local section="echo '<<<$2>>>' ; " ; shift ; fi + local NAME=$1 + local MAXAGE=$2 + shift 2 + local CMDLINE="$section$@" + + if [ ! -d $MK_VARDIR/cache ]; then mkdir -p $MK_VARDIR/cache ; fi + CACHEFILE="$MK_VARDIR/cache/$NAME.cache" + + # Check if the creation of the cache takes suspiciously long and return + # nothing if the age (access time) of $CACHEFILE.new is twice the MAXAGE + local NOW=$(date +%s) + if [ -e "$CACHEFILE.new" ] ; then + local CF_ATIME=$(stat -c %X "$CACHEFILE.new") + if [ $((NOW - CF_ATIME)) -ge $((MAXAGE * 2)) ] ; then + # Kill the process still accessing that file in case + # it is still running. This avoids overlapping processes! + fuser -k -9 "$CACHEFILE.new" >/dev/null 2>&1 + rm -f "$CACHEFILE.new" + return + fi + fi + + # Check if cache file exists and is recent enough + if [ -s "$CACHEFILE" ] ; then + local MTIME=$(stat -c %Y "$CACHEFILE") + if [ $((NOW - MTIME)) -le $MAXAGE ] ; then local USE_CACHEFILE=1 ; fi + # Output the file in any case, even if it is + # outdated. The new file will not yet be available + cat "$CACHEFILE" + fi + + # Cache file outdated and new job not yet running? Start it + if [ -z "$USE_CACHEFILE" -a ! -e "$CACHEFILE.new" ] ; then + echo "set -o noclobber ; exec > \"$CACHEFILE.new\" || exit 1 ; $CMDLINE && mv \"$CACHEFILE.new\" \"$CACHEFILE\" || rm -f \"$CACHEFILE\" \"$CACHEFILE.new\"" | nohup bash >/dev/null 2>&1 & + fi +} + +# Make run_cached available for subshells (plugins, local checks, etc.) +export -f run_cached + +echo '<<>>' +echo Version: 1.2.6b5 +echo AgentOS: linux +echo AgentDirectory: $MK_CONFDIR +echo DataDirectory: $MK_VARDIR +echo SpoolDirectory: $SPOOLDIR +echo PluginsDirectory: $PLUGINSDIR +echo LocalDirectory: $LOCALDIR + +# If we are called via xinetd, try to find only_from configuration +if [ -n "$REMOTE_HOST" ] +then + echo -n 'OnlyFrom: ' + echo $(sed -n '/^service[[:space:]]*check_mk/,/}/s/^[[:space:]]*only_from[[:space:]]*=[[:space:]]*\(.*\)/\1/p' /etc/xinetd.d/* | head -n1) +fi + +# Print out Partitions / Filesystems. (-P gives non-wrapped POSIXed output) +# Heads up: NFS-mounts are generally supressed to avoid agent hangs. +# If hard NFS mounts are configured or you have too large nfs retry/timeout +# settings, accessing those mounts from the agent would leave you with +# thousands of agent processes and, ultimately, a dead monitored system. +# These should generally be monitored on the NFS server, not on the clients. + +echo '<<>>' +# The exclusion list is getting a bit of a problem. -l should hide any remote FS but seems +# to be all but working. +excludefs="-x smbfs -x cifs -x iso9660 -x udf -x nfsv4 -x nfs -x mvfs -x zfs" +df -PTlk $excludefs | sed 1d + +# df inodes information +echo '<<>>' +echo '[df_inodes_start]' +df -PTli $excludefs | sed 1d +echo '[df_inodes_end]' + +# Filesystem usage for ZFS +if type zfs > /dev/null 2>&1 ; then + echo '<<>>' + zfs get -Hp name,quota,used,avail,mountpoint,type -t filesystem,volume || \ + zfs get -Hp name,quota,used,avail,mountpoint,type + echo '[df]' + df -PTlk -t zfs | sed 1d +fi + +# Check NFS mounts by accessing them with stat -f (System +# call statfs()). If this lasts more then 2 seconds we +# consider it as hanging. We need waitmax. +if type waitmax >/dev/null +then + STAT_VERSION=$(stat --version | head -1 | cut -d" " -f4) + STAT_BROKE="5.3.0" + + echo '<<>>' + sed -n '/ nfs4\? /s/[^ ]* \([^ ]*\) .*/\1/p' < /proc/mounts | + sed 's/\\040/ /g' | + while read MP + do + if [ $STAT_VERSION != $STAT_BROKE ]; then + waitmax -s 9 2 stat -f -c "$MP ok %b %f %a %s" "$MP" || \ + echo "$MP hanging 0 0 0 0" + else + waitmax -s 9 2 stat -f -c "$MP ok %b %f %a %s" "$MP" && \ + printf '\n'|| echo "$MP hanging 0 0 0 0" + fi + done + + echo '<<>>' + sed -n '/ cifs\? /s/[^ ]* \([^ ]*\) .*/\1/p' < /proc/mounts | + sed 's/\\040/ /g' | + while read MP + do + if [ $STAT_VERSION != $STAT_BROKE ]; then + waitmax -s 9 2 stat -f -c "$MP ok %b %f %a %s" "$MP" || \ + echo "$MP hanging 0 0 0 0" + else + waitmax -s 9 2 stat -f -c "$MP ok %b %f %a %s" "$MP" && \ + printf '\n'|| echo "$MP hanging 0 0 0 0" + fi + done +fi + +# Check mount options. Filesystems may switch to 'ro' in case +# of a read error. +echo '<<>>' +grep ^/dev < /proc/mounts + +# processes including username, without kernel processes +echo '<<>>' +ps ax -o user,vsz,rss,cputime,pid,command --columns 10000 | sed -e 1d -e 's/ *\([^ ]*\) *\([^ ]*\) *\([^ ]*\) *\([^ ]*\) *\([^ ]*\) */(\1,\2,\3,\4,\5) /' + +# Memory usage +echo '<<>>' +egrep -v '^Swap:|^Mem:|total:' < /proc/meminfo + +# Load and number of processes +echo '<<>>' +echo "$(cat /proc/loadavg) $(grep -E '^CPU|^processor' < /proc/cpuinfo | wc -l)" + +# Uptime +echo '<<>>' +cat /proc/uptime + + +# New variant: Information about speed and state in one section +echo '<<>>' +sed 1,2d /proc/net/dev +if type ethtool > /dev/null +then + for eth in $(sed -e 1,2d < /proc/net/dev | cut -d':' -f1 | sort) + do + echo "[$eth]" + ethtool $eth | egrep '(Speed|Duplex|Link detected|Auto-negotiation):' + echo -en "\tAddress: " ; cat /sys/class/net/$eth/address ; echo + done +fi + + +# Current state of bonding interfaces +if [ -e /proc/net/bonding ] ; then + echo '<<>>' + pushd /proc/net/bonding > /dev/null ; head -v -n 1000 * ; popd +fi + +# Same for Open vSwitch bonding +if type ovs-appctl > /dev/null ; then + echo '<<>>' + for bond in $(ovs-appctl bond/list | sed -e 1d | cut -f2) ; do + echo "[$bond]" + ovs-appctl bond/show $bond + done +fi + + +# Number of TCP connections in the various states +echo '<<>>' +# waitmax 10 netstat -nt | awk ' /^tcp/ { c[$6]++; } END { for (x in c) { print x, c[x]; } }' +# New implementation: netstat is very slow for large TCP tables +cat /proc/net/tcp /proc/net/tcp6 2>/dev/null | awk ' /:/ { c[$4]++; } END { for (x in c) { print x, c[x]; } }' + +# Linux Multipathing +if type multipath >/dev/null ; then + echo '<<>>' + multipath -l +fi + +# Performancecounter Platten +echo '<<>>' +date +%s +egrep ' (x?[shv]d[a-z]*|cciss/c[0-9]+d[0-9]+|emcpower[a-z]+|dm-[0-9]+|VxVM.*|mmcblk.*) ' < /proc/diskstats +if type dmsetup >/dev/null ; then + echo '[dmsetup_info]' + dmsetup info -c --noheadings --separator ' ' -o name,devno,vg_name,lv_name +fi +if [ -d /dev/vx/dsk ] ; then + echo '[vx_dsk]' + stat -c "%t %T %n" /dev/vx/dsk/*/* +fi + + +# Performancecounter Kernel +echo '<<>>' +date +%s +cat /proc/vmstat /proc/stat + +# Hardware sensors via IPMI (need ipmitool) +if type ipmitool > /dev/null +then + run_cached -s ipmi 300 "ipmitool sensor list | grep -v 'command failed' | sed -e 's/ *| */|/g' -e 's/ /_/g' -e 's/_*"'$'"//' -e 's/|/ /g' | egrep -v '^[^ ]+ na ' | grep -v ' discrete '" +fi + + +# IPMI data via ipmi-sensors (of freeipmi). Please make sure, that if you +# have installed freeipmi that IPMI is really support by your hardware. +if type ipmi-sensors >/dev/null +then + echo '<<>>' + # Newer ipmi-sensors version have new output format; Legacy format can be used + if ipmi-sensors --help | grep -q legacy-output; then + IPMI_FORMAT="--legacy-output" + else + IPMI_FORMAT="" + fi + # At least with ipmi-sensoirs 0.7.16 this group is Power_Unit instead of "Power Unit" + run_cached -s ipmi_sensors 300 "for class in Temperature Power_Unit Fan + do + ipmi-sensors $IPMI_FORMAT --sdr-cache-directory /var/cache -g "$class" | sed -e 's/ /_/g' -e 's/:_\?/ /g' -e 's@ \([^(]*\)_(\([^)]*\))@ \2_\1@' + # In case of a timeout immediately leave loop. + if [ $? = 255 ] ; then break ; fi + done" +fi + +# RAID status of Linux software RAID +echo '<<>>' +cat /proc/mdstat + +# RAID status of Linux RAID via device mapper +if type dmraid >/dev/null && DMSTATUS=$(dmraid -r) +then + echo '<<>>' + + # Output name and status + dmraid -s | grep -e ^name -e ^status + + # Output disk names of the RAID disks + DISKS=$(echo "$DMSTATUS" | cut -f1 -d\:) + + for disk in $DISKS ; do + device=$(cat /sys/block/$(basename $disk)/device/model ) + status=$(echo "$DMSTATUS" | grep ^${disk}) + echo "$status Model: $device" + done +fi + +# RAID status of LSI controllers via cfggen +if type cfggen > /dev/null ; then + echo '<<>>' + cfggen 0 DISPLAY | egrep '(Target ID|State|Volume ID|Status of volume)[[:space:]]*:' | sed -e 's/ *//g' -e 's/:/ /' +fi + +# RAID status of LSI MegaRAID controller via MegaCli. You can download that tool from: +# http://www.lsi.com/downloads/Public/MegaRAID%20Common%20Files/8.02.16_MegaCLI.zip +if type MegaCli >/dev/null ; then + MegaCli_bin="MegaCli" +elif type MegaCli64 >/dev/null ; then + MegaCli_bin="MegaCli64" +elif type megacli >/dev/null ; then + MegaCli_bin="megacli" +else + MegaCli_bin="unknown" +fi + +if [ "$MegaCli_bin" != "unknown" ]; then + echo '<<>>' + for part in $($MegaCli_bin -EncInfo -aALL -NoLog < /dev/null \ + | sed -rn 's/:/ /g; s/[[:space:]]+/ /g; s/^ //; s/ $//; s/Number of enclosures on adapter ([0-9]+).*/adapter \1/g; /^(Enclosure|Device ID|adapter) [0-9]+$/ p'); do + [ $part = adapter ] && echo "" + [ $part = 'Enclosure' ] && echo -ne "\ndev2enc" + echo -n " $part" + done + echo + $MegaCli_bin -PDList -aALL -NoLog < /dev/null | egrep 'Enclosure|Raw Size|Slot Number|Device Id|Firmware state|Inquiry|Adapter' + echo '<<>>' + $MegaCli_bin -LDInfo -Lall -aALL -NoLog < /dev/null | egrep 'Size|State|Number|Adapter|Virtual' + echo '<<>>' + $MegaCli_bin -AdpBbuCmd -GetBbuStatus -aALL -NoLog < /dev/null | grep -v Exit +fi + +# RAID status of 3WARE disk controller (by Radoslaw Bak) +if type tw_cli > /dev/null ; then + for C in $(tw_cli show | awk 'NR < 4 { next } { print $1 }'); do + echo '<<<3ware_info>>>' + tw_cli /$C show all | egrep 'Model =|Firmware|Serial' + echo '<<<3ware_disks>>>' + tw_cli /$C show drivestatus | egrep 'p[0-9]' | sed "s/^/$C\//" + echo '<<<3ware_units>>>' + tw_cli /$C show unitstatus | egrep 'u[0-9]' | sed "s/^/$C\//" + done +fi + +# RAID controllers from areca (Taiwan) +# cli64 can be found at ftp://ftp.areca.com.tw/RaidCards/AP_Drivers/Linux/CLI/ +if type cli64 >/dev/null ; then + run_cached -s arc_raid_status 300 "cli64 rsf info | tail -n +3 | head -n -2" +fi + +# VirtualBox Guests. Section must always been output. Otherwise the +# check would not be executed in case no guest additions are installed. +# And that is something the check wants to detect +echo '<<>>' +if type VBoxControl >/dev/null 2>&1 ; then + VBoxControl -nologo guestproperty enumerate | cut -d, -f1,2 + [ ${PIPESTATUS[0]} = 0 ] || echo "ERROR" +fi + +# OpenVPN Clients. Currently we assume that the configuration # is in +# /etc/openvpn. We might find a safer way to find the configuration later. +if [ -e /etc/openvpn/openvpn-status.log ] ; then + echo '<<>>' + sed -n -e '/CLIENT LIST/,/ROUTING TABLE/p' < /etc/openvpn/openvpn-status.log | sed -e 1,3d -e '$d' +fi + +# Time synchronization with NTP +if type ntpq > /dev/null 2>&1 ; then + # remove heading, make first column space separated + run_cached -s ntp 30 "waitmax 5 ntpq -np | sed -e 1,2d -e 's/^\(.\)/\1 /' -e 's/^ /%/'" +fi + +# Time synchronization with Chrony +if type chronyc > /dev/null 2>&1 ; then + # Force successful exit code. Otherwise section will be missing if daemon not running + run_cached -s chrony 30 "waitmax 5 chronyc tracking || true" +fi + +if type nvidia-settings >/dev/null && [ -S /tmp/.X11-unix/X0 ] +then + echo '<<>>' + for var in GPUErrors GPUCoreTemp + do + DISPLAY=:0 waitmax 2 nvidia-settings -t -q $var | sed "s/^/$var: /" + done +fi + +if [ -e /proc/drbd ]; then + echo '<<>>' + cat /proc/drbd +fi + +# Status of CUPS printer queues +if type lpstat > /dev/null 2>&1; then + if pgrep cups > /dev/null 2>&1; then + echo '<<>>' + CPRINTCONF=/etc/cups/printers.conf + if [ -r "$CPRINTCONF" ] ; then + LOCAL_PRINTERS=$(grep -E "<(Default)?Printer .*>" $CPRINTCONF | awk '{print $2}' | sed -e 's/>//') + lpstat -p | while read LINE + do + PRINTER=$(echo $LINE | awk '{print $2}') + if echo "$LOCAL_PRINTERS" | grep -q "$PRINTER"; then + echo $LINE + fi + done + echo '---' + lpstat -o | while read LINE + do + PRINTER=${LINE%%-*} + if echo "$LOCAL_PRINTERS" | grep -q "$PRINTER"; then + echo $LINE + fi + done + else + lpstat -p + echo '---' + lpstat -o | sort + fi + fi +fi + +# Heartbeat monitoring +# Different handling for heartbeat clusters with and without CRM +# for the resource state +if [ -S /var/run/heartbeat/crm/cib_ro -o -S /var/run/crm/cib_ro ] || pgrep crmd > /dev/null 2>&1; then + echo '<<>>' + crm_mon -1 -r | grep -v ^$ | sed 's/^ //; /^\sResource Group:/,$ s/^\s//; s/^\s/_/g' +fi +if type cl_status > /dev/null 2>&1; then + echo '<<>>' + cl_status rscstatus + + echo '<<>>' + for NODE in $(cl_status listnodes); do + if [ $NODE != $(echo $HOSTNAME | tr 'A-Z' 'a-z') ]; then + STATUS=$(cl_status nodestatus $NODE) + echo -n "$NODE $STATUS" + for LINK in $(cl_status listhblinks $NODE 2>/dev/null); do + echo -n " $LINK $(cl_status hblinkstatus $NODE $LINK)" + done + echo + fi + done +fi + +# Postfix mailqueue monitoring +# +# Only handle mailq when postfix user is present. The mailq command is also +# available when postfix is not installed. But it produces different outputs +# which are not handled by the check at the moment. So try to filter out the +# systems not using postfix by searching for the postfix user.a +# +# Cannot take the whole outout. This could produce several MB of agent output +# on blocking queues. +# Only handle the last 6 lines (includes the summary line at the bottom and +# the last message in the queue. The last message is not used at the moment +# but it could be used to get the timestamp of the last message. +if type postconf >/dev/null ; then + echo '<<>>' + postfix_queue_dir=$(postconf -h queue_directory) + postfix_count=$(find $postfix_queue_dir/deferred -type f | wc -l) + postfix_size=$(du -ks $postfix_queue_dir/deferred | awk '{print $1 }') + if [ $postfix_count -gt 0 ] + then + echo -- $postfix_size Kbytes in $postfix_count Requests. + else + echo Mail queue is empty + fi +elif [ -x /usr/sbin/ssmtp ] ; then + echo '<<>>' + mailq 2>&1 | sed 's/^[^:]*: \(.*\)/\1/' | tail -n 6 +fi + +#Check status of qmail mailqueue +if type qmail-qstat >/dev/null +then + echo "<<>>" + qmail-qstat +fi + +# Check status of OMD sites +if type omd >/dev/null +then + run_cached -s omd_status 60 "omd status --bare --auto" +fi + + +# Welcome the ZFS check on Linux +# We do not endorse running ZFS on linux if your vendor doesnt support it ;) +# check zpool status +if type zpool >/dev/null; then + echo "<<>>" + zpool status -x +fi + + +# Fileinfo-Check: put patterns for files into /etc/check_mk/fileinfo.cfg +if [ -r "$MK_CONFDIR/fileinfo.cfg" ] ; then + echo '<<>>' + date +%s + stat -c "%n|%s|%Y" $(cat "$MK_CONFDIR/fileinfo.cfg") +fi + +# Get stats about OMD monitoring cores running on this machine. +# Since cd is a shell builtin the check does not affect the performance +# on non-OMD machines. +if cd /omd/sites +then + echo '<<>>' + for site in * + do + if [ -S "/omd/sites/$site/tmp/run/live" ] ; then + echo "[$site]" + echo -e "GET status" | waitmax 3 /omd/sites/$site/bin/unixcat /omd/sites/$site/tmp/run/live + fi + done +fi + +# Get statistics about monitored jobs. Below the job directory there +# is a sub directory per user that ran a job. That directory must be +# owned by the user so that a symlink or hardlink attack for reading +# arbitrary files can be avoided. +if pushd $MK_VARDIR/job >/dev/null; then + echo '<<>>' + for username in * + do + if [ -d "$username" ] && cd "$username" ; then + su "$username" -c "head -n -0 -v *" + cd .. + fi + done + popd > /dev/null +fi + +# Gather thermal information provided e.g. by acpi +# At the moment only supporting thermal sensors +if ls /sys/class/thermal/thermal_zone* >/dev/null 2>&1; then + echo '<<>>' + for F in /sys/class/thermal/thermal_zone*; do + echo -n "${F##*/} " + if [ ! -e $F/mode ] ; then echo -n "- " ; fi + cat $F/{mode,type,temp,trip_point_*} | tr \\n " " + echo + done +fi + +# Libelle Business Shadow +if type trd >/dev/null; then + echo "<<>>" + trd -s +fi + +# MK's Remote Plugin Executor +if [ -e "$MK_CONFDIR/mrpe.cfg" ] +then + echo '<<>>' + grep -Ev '^[[:space:]]*($|#)' "$MK_CONFDIR/mrpe.cfg" | \ + while read descr cmdline + do + PLUGIN=${cmdline%% *} + OUTPUT=$(eval "$cmdline") + echo -n "(${PLUGIN##*/}) $descr $? $OUTPUT" | tr \\n \\1 + echo + done +fi + + +# Local checks +echo '<<>>' +if cd $LOCALDIR ; then + for skript in $(ls) ; do + if [ -f "$skript" -a -x "$skript" ] ; then + ./$skript + fi + done + # Call some plugins only every X'th minute + for skript in [1-9]*/* ; do + if [ -x "$skript" ] ; then + run_cached local_${skript//\//\\} ${skript%/*} "$skript" + fi + done +fi + +# Plugins +if cd $PLUGINSDIR ; then + for skript in $(ls) ; do + if [ -f "$skript" -a -x "$skript" ] ; then + ./$skript + fi + done + # Call some plugins only every Xth minute + for skript in [1-9]*/* ; do + if [ -x "$skript" ] ; then + run_cached plugins_${skript//\//\\} ${skript%/*} "$skript" + fi + done +fi + +# Agent output snippets created by cronjobs, etc. +if [ -d "$SPOOLDIR" ] +then + pushd "$SPOOLDIR" > /dev/null + now=$(date +%s) + + for file in * + do + # output every file in this directory. If the file is prefixed + # with a number, then that number is the maximum age of the + # file in seconds. If the file is older than that, it is ignored. + maxage="" + part="$file" + + # Each away all digits from the front of the filename and + # collect them in the variable maxage. + while [ "${part/#[0-9]/}" != "$part" ] + do + maxage=$maxage${part:0:1} + part=${part:1} + done + + # If there is at least one digit, than we honor that. + if [ "$maxage" ] ; then + mtime=$(stat -c %Y "$file") + if [ $((now - mtime)) -gt $maxage ] ; then + continue + fi + fi + + # Output the file + cat "$file" + done + popd > /dev/null +fi diff --git a/roles/oam/files/librenms/distro b/roles/oam/files/librenms/distro new file mode 100644 index 0000000..61ad248 --- /dev/null +++ b/roles/oam/files/librenms/distro @@ -0,0 +1,114 @@ +#!/usr/bin/env bash +# Detects which OS and if it is Linux then it will detect which Linux Distribution. + +OS=`uname -s` +REV=`uname -r` +MACH=`uname -m` + +if [ "${OS}" = "SunOS" ] ; then + OS=Solaris + ARCH=`uname -p` + OSSTR="${OS} ${REV}(${ARCH} `uname -v`)" + +elif [ "${OS}" = "AIX" ] ; then + OSSTR="${OS} `oslevel` (`oslevel -r`)" + +elif [ "${OS}" = "Linux" ] ; then + KERNEL=`uname -r` + + if [ -f /etc/fedora-release ]; then + DIST=$(cat /etc/fedora-release | awk '{print $1}') + REV=`cat /etc/fedora-release | sed s/.*release\ // | sed s/\ .*//` + + elif [ -f /etc/redhat-release ] ; then + DIST=$(cat /etc/redhat-release | awk '{print $1}') + if [ "${DIST}" = "CentOS" ]; then + DIST="CentOS" + elif [ "${DIST}" = "Mandriva" ]; then + DIST="Mandriva" + PSEUDONAME=`cat /etc/mandriva-release | sed s/.*\(// | sed s/\)//` + REV=`cat /etc/mandriva-release | sed s/.*release\ // | sed s/\ .*//` + elif [ -f /etc/oracle-release ]; then + DIST="Oracle" + else + DIST="RedHat" + fi + + PSEUDONAME=`cat /etc/redhat-release | sed s/.*\(// | sed s/\)//` + REV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//` + + elif [ -f /etc/mandrake-release ] ; then + DIST='Mandrake' + PSEUDONAME=`cat /etc/mandrake-release | sed s/.*\(// | sed s/\)//` + REV=`cat /etc/mandrake-release | sed s/.*release\ // | sed s/\ .*//` + + elif [ -f /etc/devuan_version ] ; then + DIST="Devuan `cat /etc/devuan_version`" + REV="" + + elif [ -f /etc/debian_version ] ; then + DIST="Debian `cat /etc/debian_version`" + REV="" + ID=`lsb_release -i | awk -F ':' '{print $2}' | sed 's/ //g'` + if [ "${ID}" = "Raspbian" ] ; then + DIST="Raspbian `cat /etc/debian_version`" + fi + + elif [ -f /etc/gentoo-release ] ; then + DIST="Gentoo" + REV=$(tr -d '[[:alpha:]]' >>' + +# requires dmidecode +for FIELD in bios-vendor bios-version bios-release-date system-manufacturer system-product-name system-version system-serial-number system-uuid baseboard-manufacturer baseboard-product-name baseboard-version baseboard-serial-number baseboard-asset-tag chassis-manufacturer chassis-type chassis-version chassis-serial-number chassis-asset-tag processor-family processor-manufacturer processor-version processor-frequency +do + echo $FIELD="$(dmidecode -s $FIELD | grep -v '^#')" +done diff --git a/roles/oam/files/librenms/dpkg.sh b/roles/oam/files/librenms/dpkg.sh new file mode 100644 index 0000000..e89e2a0 --- /dev/null +++ b/roles/oam/files/librenms/dpkg.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Cache the file for 30 minutes +# If you want to override this, put the command in cron. +# We cache because it is a 1sec delay, which is painful for the poller +if [ -x /usr/bin/dpkg-query ]; then + DATE=$(date +%s) + FILE=/var/cache/librenms/agent-local-dpkg + + [ -d /var/cache/librenms ] || mkdir -p /var/cache/librenms + + if [ ! -e $FILE ]; then + dpkg-query -W --showformat='${Status} ${Package} ${Version} ${Architecture} ${Installed-Size}\n'|grep " installed "|cut -d\ -f4- > $FILE + fi + FILEMTIME=$(stat -c %Y $FILE) + FILEAGE=$(($DATE-$FILEMTIME)) + if [ $FILEAGE -gt 1800 ]; then + dpkg-query -W --showformat='${Status} ${Package} ${Version} ${Architecture} ${Installed-Size}\n'|grep " installed "|cut -d\ -f4- > $FILE + fi + echo "<<>>" + cat $FILE +fi + diff --git a/roles/oam/files/librenms/ntp-client b/roles/oam/files/librenms/ntp-client new file mode 100644 index 0000000..eccb5e5 --- /dev/null +++ b/roles/oam/files/librenms/ntp-client @@ -0,0 +1,34 @@ +#!/bin/sh +# Please make sure the paths below are correct. +# Alternatively you can put them in $0.conf, meaning if you've named +# this script ntp-client then it must go in ntp-client.conf . +# +# NTPQV output version of "ntpq -c rv" +# Version 4 is the most common and up to date version. +# +# If you are unsure, which to set, run this script and make sure that +# the JSON output variables match that in "ntpq -c rv". +# +################################################################ +# Don't change anything unless you know what are you doing # +################################################################ +BIN_NTPQ='/usr/bin/env ntpq' +BIN_GREP='/usr/bin/env grep' +BIN_AWK='/usr/bin/env awk' + +CONFIG=$0".conf" +if [ -f "$CONFIG" ]; then + # shellcheck disable=SC1090 + . "$CONFIG" +fi + +NTP_OFFSET=$($BIN_NTPQ -c rv | $BIN_GREP "offset" | $BIN_AWK -Foffset= '{print $2}' | $BIN_AWK -F, '{print $1}') +NTP_FREQUENCY=$($BIN_NTPQ -c rv | $BIN_GREP "frequency" | $BIN_AWK -Ffrequency= '{print $2}' | $BIN_AWK -F, '{print $1}') +NTP_SYS_JITTER=$($BIN_NTPQ -c rv | $BIN_GREP "sys_jitter" | $BIN_AWK -Fsys_jitter= '{print $2}' | $BIN_AWK -F, '{print $1}') +NTP_CLK_JITTER=$($BIN_NTPQ -c rv | $BIN_GREP "clk_jitter" | $BIN_AWK -Fclk_jitter= '{print $2}' | $BIN_AWK -F, '{print $1}') +NTP_WANDER=$($BIN_NTPQ -c rv | $BIN_GREP "clk_wander" | $BIN_AWK -Fclk_wander= '{print $2}' | $BIN_AWK -F, '{print $1}') +NTP_VERSION=$($BIN_NTPQ -c rv | $BIN_GREP "version" | $BIN_AWK -F'ntpd ' '{print $2}' | $BIN_AWK -F. '{print $1}') + +echo '{"data":{"offset":"'"$NTP_OFFSET"'","frequency":"'"$NTP_FREQUENCY"'","sys_jitter":"'"$NTP_SYS_JITTER"'","clk_jitter":"'"$NTP_CLK_JITTER"'","clk_wander":"'"$NTP_WANDER"'"},"version":"'"$NTP_VERSION"'","error":"0","errorString":""}' + +exit 0 diff --git a/roles/oam/files/librenms/os-updates.sh b/roles/oam/files/librenms/os-updates.sh new file mode 100644 index 0000000..33e1f9c --- /dev/null +++ b/roles/oam/files/librenms/os-updates.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +################################################################ +# copy this script to /etc/snmp/ and make it executable: # +# chmod +x /etc/snmp/os-updates.sh # +# ------------------------------------------------------------ # +# edit your snmpd.conf and include: # +# extend osupdate /opt/os-updates.sh # +#--------------------------------------------------------------# +# restart snmpd and activate the app for desired host # +#--------------------------------------------------------------# +# please make sure you have the path/binaries below # +################################################################ +BIN_WC='/usr/bin/wc' +BIN_GREP='/bin/grep' +CMD_GREP='-c' +CMD_WC='-l' +BIN_ZYPPER='/usr/bin/zypper' +CMD_ZYPPER='-q lu' +BIN_YUM='/usr/bin/yum' +CMD_YUM='-q check-update' +BIN_DNF='/usr/bin/dnf' +CMD_DNF='-q check-update' +BIN_APT='/usr/bin/apt-get' +CMD_APT='-qq -s upgrade' +BIN_PACMAN='/usr/bin/pacman' +CMD_PACMAN='-Sup' + +################################################################ +# Don't change anything unless you know what are you doing # +################################################################ +if [ -f $BIN_ZYPPER ]; then + # OpenSUSE + UPDATES=`$BIN_ZYPPER $CMD_ZYPPER | $BIN_WC $CMD_WC` + if [ $UPDATES -ge 2 ]; then + echo $(($UPDATES-2)); + else + echo "0"; + fi +elif [ -f $BIN_DNF ]; then + # Fedora + UPDATES=`$BIN_DNF $CMD_DNF | $BIN_WC $CMD_WC` + if [ $UPDATES -ge 1 ]; then + echo $(($UPDATES-1)); + else + echo "0"; + fi +elif [ -f $BIN_PACMAN ]; then + # Arch + UPDATES=`$BIN_PACMAN $CMD_PACMAN | $BIN_WC $CMD_WC` + if [ $UPDATES -ge 1 ]; then + echo $(($UPDATES-1)); + else + echo "0"; + fi +elif [ -f $BIN_YUM ]; then + # CentOS / Redhat + UPDATES=`$BIN_YUM $CMD_YUM | $BIN_WC $CMD_WC` + if [ $UPDATES -ge 1 ]; then + echo $(($UPDATES-1)); + else + echo "0"; + fi +elif [ -f $BIN_APT ]; then + # Debian / Devuan / Ubuntu + UPDATES=`$BIN_APT $CMD_APT | $BIN_GREP $CMD_GREP 'Inst'` + if [ $UPDATES -ge 1 ]; then + echo $UPDATES; + else + echo "0"; + fi +else + echo "0"; +fi diff --git a/roles/oam/files/librenms/postfix-queues b/roles/oam/files/librenms/postfix-queues new file mode 100644 index 0000000..1d3491e --- /dev/null +++ b/roles/oam/files/librenms/postfix-queues @@ -0,0 +1,13 @@ +#!/bin/bash + +#Written by Valec 2006. Steal and share. +#Get postfix queue lengths + +#extend mailq /opt/observer/scripts/getmailq.sh + +QUEUES="incoming active deferred hold" + +for i in $QUEUES; do + COUNT=$(qshape "$i" | grep TOTAL | awk '{print $2}') + printf "$COUNT\n" +done diff --git a/roles/oam/files/librenms/postfixdetailed b/roles/oam/files/librenms/postfixdetailed new file mode 100644 index 0000000..e6cb1e9 --- /dev/null +++ b/roles/oam/files/librenms/postfixdetailed @@ -0,0 +1,548 @@ +#!/usr/bin/env perl + +# add this to your snmpd.conf file as below +# extend postfixdetailed /etc/snmp/postfixdetailed + +# The cache file to use. +my $cache='/var/cache/postfixdetailed'; + +# the location of pflogsumm +my $pflogsumm='/usr/bin/env pflogsumm'; + +#totals +# 847 received = received +# 852 delivered = delivered +# 0 forwarded = forwarded +# 3 deferred (67 deferrals)= deferred +# 0 bounced = bounced +# 593 rejected (41%) = rejected +# 0 reject warnings = rejectw +# 0 held = held +# 0 discarded (0%) = discarded + +# 16899k bytes received = bytesr +# 18009k bytes delivered = bytesd +# 415 senders = senders +# 266 sending hosts/domains = sendinghd +# 15 recipients = recipients +# 9 recipient hosts/domains = recipienthd + +######message deferral detail +#Connection refused = deferralcr +#Host is down = deferralhid + +########message reject detail +#Client host rejected = chr +#Helo command rejected: need fully-qualified hostname = hcrnfqh +#Sender address rejected: Domain not found = sardnf +#Sender address rejected: not owned by user = sarnobu +#blocked using = bu +#Recipient address rejected: User unknown = raruu +#Helo command rejected: Invalid name = hcrin +#Sender address rejected: need fully-qualified address = sarnfqa +#Recipient address rejected: Domain not found = rardnf +#Recipient address rejected: need fully-qualified address = rarnfqa +#Improper use of SMTP command pipelining = iuscp +#Message size exceeds fixed limit = msefl +#Server configuration error = sce +#Server configuration problem = scp +#unknown reject reason = urr + +my $old=''; + +#reads in the old data if it exists +if ( -f $cache ){ + open(my $fh, "<", $cache) or die "Can't open '".$cache."'"; + # if this is over 2048, something is most likely wrong + read($fh , $old , 2048); + close($fh); +} + +my ( $received, + $delivered, + $forwarded, + $deferred, + $bounced, + $rejected, + $rejectw, + $held, + $discarded, + $bytesr, + $bytesd, + $senders, + $sendinghd, + $recipients, + $recipienthd, + $deferralcr, + $deferralhid, + $chr, + $hcrnfqh, + $sardnf, + $sarnobu, + $bu, + $raruu, + $hcrin, + $sarnfqa, + $rardnf, + $rarnfqa, + $iuscp, + $sce, + $scp, + $urr, + $msefl) = split ( /\n/, $old ); + +if ( ! defined( $received ) ){ $received=0; } +if ( ! defined( $delivered ) ){ $delivered=0; } +if ( ! defined( $forwarded ) ){ $forwarded=0; } +if ( ! defined( $deferred ) ){ $deferred=0; } +if ( ! defined( $bounced ) ){ $bounced=0; } +if ( ! defined( $rejected ) ){ $rejected=0; } +if ( ! defined( $rejectw ) ){ $rejectw=0; } +if ( ! defined( $held ) ){ $held=0; } +if ( ! defined( $discarded ) ){ $discarded=0; } +if ( ! defined( $bytesr ) ){ $bytesr=0; } +if ( ! defined( $bytesd ) ){ $bytesd=0; } +if ( ! defined( $senders ) ){ $senders=0; } +if ( ! defined( $sendinghd ) ){ $sendinghd=0; } +if ( ! defined( $recipients ) ){ $recipients=0; } +if ( ! defined( $recipienthd ) ){ $recipienthd=0; } +if ( ! defined( $deferralcr ) ){ $deferralcr=0; } +if ( ! defined( $deferralhid ) ){ $deferralhid=0; } +if ( ! defined( $chr ) ){ $chr=0; } +if ( ! defined( $hcrnfqh ) ){ $hcrnfqh=0; } +if ( ! defined( $sardnf ) ){ $sardnf=0; } +if ( ! defined( $sarnobu ) ){ $sarnobu=0; } +if ( ! defined( $bu ) ){ $bu=0; } +if ( ! defined( $raruu ) ){ $raruu=0; } +if ( ! defined( $hcrin ) ){ $hcrin=0; } +if ( ! defined( $sarnfqa ) ){ $sarnfqa=0; } +if ( ! defined( $rardnf ) ){ $rardnf=0; } +if ( ! defined( $rarnfqa ) ){ $rarnfqa=0; } +if ( ! defined( $iuscp ) ){ $iuscp=0; } +if ( ! defined( $msefl ) ){ $msefl=0; } +if ( ! defined( $sce ) ){ $sce=0; } +if ( ! defined( $scp ) ){ $scp=0; } +if ( ! defined( $urr ) ){ $urr=0; } + +#init current variables +my $receivedC=0; +my $deliveredC=0; +my $forwardedC=0; +my $deferredC=0; +my $bouncedC=0; +my $rejectedC=0; +my $rejectwC=0; +my $heldC=0; +my $discardedC=0; +my $bytesrC=0; +my $bytesdC=0; +my $sendersC=0; +my $sendinghdC=0; +my $recipientsC=0; +my $recipienthdC=0; +my $deferralcrC=0; +my $deferralhidC=0; +my $hcrnfqhC=0; +my $sardnfC=0; +my $sarnobuC=0; +my $buC=0; +my $raruuC=0; +my $hcrinC=0; +my $sarnfqaC=0; +my $rardnfC=0; +my $rarnfqaC=0; +my $iuscpC=0; +my $mseflC=0; +my $sceC=0; +my $scpC=0; +my $urrC=0; + +sub newValue{ + my $old=$_[0]; + my $new=$_[1]; + + #if new is undefined, just default to 0... this should never happen + if ( !defined( $new ) ){ + warn('New not defined'); + return 0; + } + + #sets it to 0 if old is not defined + if ( !defined( $old ) ){ + warn('Old not defined'); + $old=0; + } + + #make sure they are both numberic and if not set to zero + if( $old !~ /^[0123456789]*$/ ){ + warn('Old not numeric'); + $old=0; + } + if( $new !~ /^[0123456789]*$/ ){ + warn('New not numeric'); + $new=0; + } + + #log rotation happened + if ( $old > $new ){ + return $new; + }; + + return $new - $old; +} + + +my $output=`$pflogsumm /var/log/maillog`; + +#holds RBL values till the end when it is compared to the old one +my $buNew=0; + + +#holds client host rejected values till the end when it is compared to the old one +my $chrNew=0; + +# holds recipient address rejected values till the end when it is compared to the old one +my $raruuNew=0; + +#holds the current values for checking later +my $current=''; + +my @outputA=split( /\n/, $output ); +my $int=0; +while ( defined( $outputA[$int] ) ){ + my $line=$outputA[$int]; + + $line=~s/^ *//; + $line=~s/ +/ /g; + $line=~s/\)$//; + + my $handled=0; + + #received line + if ( ( $line =~ /[0123456789] received$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $receivedC=$line; + $received=newValue( $received, $line ); + $handled=1; + } + + #delivered line + if ( ( $line =~ /[0123456789] delivered$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $deliveredC=$line; + $delivered=newValue( $delivered, $line ); + $handled=1; + } + + #forward line + if ( ( $line =~ /[0123456789] forwarded$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $forwardedC=$line; + $forwarded=newValue( $forwarded, $line ); + $handled=1; + } + + #defereed line + if ( ( $line =~ /[0123456789] deferred \(/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $deferredC=$line; + $deferred=newValue( $deferred, $line ); + $handled=1; + } + + #bounced line + if ( ( $line =~ /[0123456789] bounced$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $bouncedC=$line; + $bounced=newValue( $bounced, $line ); + $handled=1; + } + + #rejected line + if ( ( $line =~ /[0123456789] rejected \(/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $rejectedC=$line; + $rejected=newValue( $rejected, $line ); + $handled=1; + } + + #reject warning line + if ( ( $line =~ /[0123456789] reject warnings/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $rejectwC=$line; + $rejectw=newValue( $rejectw, $line ); + $handled=1; + } + + #held line + if ( ( $line =~ /[0123456789] held$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $heldC=$line; + $held=newValue( $held, $line ); + $handled=1; + } + + #discarded line + if ( ( $line =~ /[0123456789] discarded \(/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $discardedC=$line; + $discarded=newValue( $discarded, $line ); + $handled=1; + } + + #bytes received line + if ( ( $line =~ /[0123456789kM] bytes received$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $line=~s/k/000/; + $line=~s/M/000000/; + $bytesrC=$line; + $bytesr=newValue( $bytesr, $line ); + $handled=1; + } + + #bytes delivered line + if ( ( $line =~ /[0123456789kM] bytes delivered$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $line=~s/k/000/; + $line=~s/M/000000/; + $bytesdC=$line; + $bytesd=newValue( $bytesd, $line ); + $handled=1; + } + + #senders line + if ( ( $line =~ /[0123456789] senders$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $sendersC=$line; + $senders=newValue( $senders, $line ); + $handled=1; + } + + #sendering hosts/domains line + if ( ( $line =~ /[0123456789] sending hosts\/domains$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $sendinghdC=$line; + $sendinghd=newValue( $sendinghd, $line ); + $handled=1; + } + + #recipients line + if ( ( $line =~ /[0123456789] recipients$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $recipientsC=$line; + $recipients=newValue( $recipients, $line ); + $handled=1; + } + + #recipients line + if ( ( $line =~ /[0123456789] recipient hosts\/domains$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $recipienthdC=$line; + $recipienthd=newValue( $recipienthd, $line ); + $handled=1; + } + + # deferrals connectios refused + if ( ( $line =~ /[0123456789] 25\: Connection refused$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $deferralcrC=$line; + $deferralcr=newValue( $deferralcr, $line ); + $handled=1; + } + + # deferrals Host is down + if ( ( $line =~ /Host is down$/ ) && ( ! $handled ) ){ + $line=~s/ .*//; + $deferralcrC=$line; + $deferralhidC=$line; + $deferralhid=newValue( $deferralhid, $line ); + $handled=1; + } + + # Client host rejected + if ( ( $line =~ /Client host rejected/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $chrNew=$chrNew + $line; + $handled=1; + } + + #Helo command rejected: need fully-qualified hostname + if ( ( $line =~ /Helo command rejected\: need fully\-qualified hostname/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $hcrnfqhC=$line; + $hcrnfqh=newValue( $hcrnfqh, $line ); + $handled=1; + } + + #Sender address rejected: Domain not found + if ( ( $line =~ /Sender address rejected\: Domain not found/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $sardnfC=$line; + $sardnf=newValue( $sardnf, $line ); + $handled=1; + } + + #Sender address rejected: not owned by user + if ( ( $line =~ /Sender address rejected\: not owned by user/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $sarnobuC=$line; + $sarnobu=newValue( $sarnobu, $line ); + $handled=1; + } + + #blocked using + # These lines are RBLs so there will be more than one. + # Use $buNew to add them all up. + if ( ( $line =~ /blocked using/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $buNew=$buNew + $line; + $handled=1; + } + + #Recipient address rejected: User unknown + if ( ( $line =~ /Recipient address rejected\: User unknown/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $raruuNew=$raruuNew + $line; + $handled=1; + } + + #Helo command rejected: Invalid name + if ( ( $line =~ /Helo command rejected\: Invalid name/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $hcrinC=$line; + $hcrin=newValue( $hcrin, $line ); + } + + #Sender address rejected: need fully-qualified address + if ( ( $line =~ /Sender address rejected\: need fully-qualified address/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $sarnfqaC=$line; + $sarnfqa=newValue( $sarnfqa, $line ); + } + + #Recipient address rejected: Domain not found + if ( ( $line =~ /Recipient address rejected\: Domain not found/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $rardnfC=$line; + $rardnf=newValue( $rardnf, $line ); + } + + #Improper use of SMTP command pipelining + if ( ( $line =~ /Improper use of SMTP command pipelining/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $iuscpC=$line; + $iuscp=newValue( $iuscp, $line ); + } + + #Message size exceeds fixed limit + if ( ( $line =~ /Message size exceeds fixed limit/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $mseflC=$line; + $msefl=newValue( $msefl, $line ); + } + + #Server configuration error + if ( ( $line =~ /Server configuration error/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $sceC=$line; + $sce=newValue( $sce, $line ); + } + + #Server configuration problem + if ( ( $line =~ /Server configuration problem/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $scpC=$line; + $scp=newValue( $scp, $line ); + } + + #unknown reject reason + if ( ( $line =~ /unknown reject reason/ ) && ( ! $handled ) ){ + $line=~s/.*\: //g; + $urrC=$line; + $urr=newValue( $urr, $line ); + } + + $int++; +} + + +# final client host rejected total +$chr=newValue( $chr, $chrNew ); + +# final RBL total +$bu=newValue( $bu, $buNew ); + +# final recipient address rejected total +$raruu=newValue( $raruu, $raruuNew ); + +my $data=$received."\n". + $delivered."\n". + $forwarded."\n". + $deferred."\n". + $bounced."\n". + $rejected."\n". + $rejectw."\n". + $held."\n". + $discarded."\n". + $bytesr."\n". + $bytesd."\n". + $senders."\n". + $sendinghd."\n". + $recipients."\n". + $recipienthd."\n". + $deferralcr."\n". + $deferralhid."\n". + $chr."\n". + $hcrnfqh."\n". + $sardnf."\n". + $sarnobu."\n". + $bu."\n". + $raruu."\n". + $hcrin."\n". + $sarnfqa."\n". + $rardnf."\n". + $rarnfqa."\n". + $iuscp."\n". + $sce."\n". + $scp."\n". + $urr."\n". + $msefl."\n"; + +print $data; + +my $current=$receivedC."\n". + $deliveredC."\n". + $forwardedC."\n". + $deferredC."\n". + $bouncedC."\n". + $rejectedC."\n". + $rejectwC."\n". + $heldC."\n". + $discardedC."\n". + $bytesrC."\n". + $bytesdC."\n". + $sendersC."\n". + $sendinghdC."\n". + $recipientsC."\n". + $recipienthdC."\n". + $deferralcrC."\n". + $deferralhidC."\n". + $chrNew."\n". + $hcrnfqhC."\n". + $sardnfC."\n". + $sarnobuC."\n". + $buNew."\n". + $raruuNew."\n". + $hcrinC."\n". + $sarnfqaC."\n". + $rardnfC."\n". + $rarnfqaC."\n". + $iuscpC."\n". + $sceC."\n". + $scpC."\n". + $urrC."\n". + $mseflC."\n"; + +open(my $fh, ">", $cache) or die "Can't open '".$cache."'"; +print $fh $current; +close($fh); diff --git a/roles/oam/handlers/main.yml b/roles/oam/handlers/main.yml new file mode 100644 index 0000000..da5fa21 --- /dev/null +++ b/roles/oam/handlers/main.yml @@ -0,0 +1,7 @@ +--- +- name: Enable and start check_mk socket + ansible.builtin.systemd: + name: check_mk.socket + enabled: true + state: started + daemon_reload: true diff --git a/roles/oam/tasks/main.yml b/roles/oam/tasks/main.yml new file mode 100644 index 0000000..81d78ca --- /dev/null +++ b/roles/oam/tasks/main.yml @@ -0,0 +1,57 @@ +--- +# LibreNMS / check_mk agent — port of Modules/OAM/oam-librenms.sh. + +- name: Ensure /usr/lib/check_mk_agent tree exists + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: root + group: root + mode: "0755" + loop: + - /usr/lib/check_mk_agent + - /usr/lib/check_mk_agent/plugins + - /usr/lib/check_mk_agent/local + +- name: Deploy distro helper + ansible.builtin.copy: + src: librenms/distro + dest: /usr/local/bin/distro + owner: root + group: root + mode: "0755" + +- name: Deploy check_mk_agent + ansible.builtin.copy: + src: librenms/check_mk_agent + dest: /usr/bin/check_mk_agent + owner: root + group: root + mode: "0755" + +- name: Deploy check_mk systemd units + ansible.builtin.copy: + src: "librenms/{{ item.src }}" + dest: "/etc/systemd/system/{{ item.src }}" + owner: root + group: root + mode: "0644" + loop: + - { src: check_mk@.service } + - { src: check_mk.socket } + notify: Enable and start check_mk socket + +- name: Deploy check_mk local plugins + ansible.builtin.copy: + src: "librenms/{{ item }}" + dest: "/usr/lib/check_mk_agent/local/{{ item }}" + owner: root + group: root + mode: "0755" + loop: + - dmi.sh + - dpkg.sh + - ntp-client + - os-updates.sh + - postfixdetailed + - postfix-queues