From: John Runyon Date: Mon, 18 Dec 2023 16:18:35 +0000 (-0600) Subject: asterisk plugins X-Git-Url: https://jfr.im/git/munin-plugins.git/commitdiff_plain/575d86d9a273434380dddf162ac2bda69041ed09 asterisk plugins --- diff --git a/asterisk b/asterisk new file mode 100755 index 0000000..bca322e --- /dev/null +++ b/asterisk @@ -0,0 +1,444 @@ +#!/usr/bin/perl -w +# -*- cperl -*- + +=head1 NAME + +asterisk - Multigraph-capable plugin to monitor Asterisk + +=head1 NOTES + +This plugin will produce multiple graphs showing: + + - total number of active channels (replaces asterisk_channels), + together with breakdown of specific channel types (replaces + asterisk_channelstypes); + + - the number of messages in all voicemail boxes (replaces + asterisk_voicemail); + + - DEPRECATED: the number of active MeetMe conferences and users connected to + them (replace asterisk_meetme and asterisk_meetmeusers, respectively); + + - the number of active ConfBridge conferences (e.g. non-empty ones) and users + connected to them + + - the number of active channels for a given codec, for both SIP and + IAX2 channels (replaces asterisk_sipchannels and asterisk_codecs). + +=head1 CONFIGURATION + +The following configuration parameters are used by this plugin + + [asterisk] + env.host - hostname to connect to + env.port - port number to connect to + env.username - username used for authentication + env.secret - secret used for authentication + env.channels - The channel types to look for + env.codecsx - List of codec IDs (hexadecimal values) + env.codecs - List of codecs names, matching codecsx order + env.enable_meetme - Set to 1 to enable graphs for the MeetMe application + env.enable_confbridge - Set to 1 to enable graphs for the ConfBridge application + +The "username" and "secret" parameters are mandatory, and have no +defaults. + +=head2 DEFAULT CONFIGURATION + + [asterisk] + env.host 127.0.0.1 + env.port 5038 + env.channels Zap IAX2 SIP + env.codecsx 0x2 0x4 0x8 + env.codecs gsm ulaw alaw + env.enable_meetme 0 + env.enable_confbridge 1 + +=head2 WILDCARD CONFIGURATION + +It's possible to use the plugin in a virtual-node capacity, in which +case the host configuration will default to the hostname following the +underscore: + + [asterisk_someserver] + env.host someserver + env.port 5038 + +=head1 AUTHOR + +Copyright (C) 2005-2006 Rodolphe Quiédeville +Copyright (C) 2012 Diego Elio Pettenò + +=head1 LICENSE + +GPLv2 + +=head1 MAGIC MARKERS + + #%# family=auto + #%# capabilities=autoconf + +=cut + +use strict; +use Munin::Plugin; +use IO::Socket; + +# See the following and its subpages for change history in the AMI protocol: +# https://wiki.asterisk.org/wiki/display/AST/Asterisk+Manager+Interface+%28AMI%29+Changes +sub asterisk_command { + my ($socket, $command) = @_; + my $line, my $reply; + + $socket->print("Action: command\nCommand: $command\n\n"); + + # Response: (Error|Follows|Success) + $line = $socket->getline; + if ($line !~ /^Response: Success\r?\n$/) { + while ( $line = $socket->getline and $line !~ /^\r?\n$/ ) { + print STDERR "COMMAND: Ignoring unwanted line: $line" if $Munin::Plugin::DEBUG; + } + return undef; + } + + # Message: Command output follows + $line = $socket->getline; + print STDERR "COMMAND got response: $line" if $Munin::Plugin::DEBUG; + + # Until we get the --END COMMAND-- marker, it's the command's output. + while ( $line = $socket->getline and $line =~ /^Output:/ ) { + print STDERR "COMMAND: got response: $line" if $Munin::Plugin::DEBUG; + # Don't keep the "Output: " part of the response + substr($line, 0, 8, ''); + $reply .= $line; + } + return $reply; +} + +$0 =~ /asterisk(?:_(.+))$/; +my $hostname = $1; + +my $peeraddr = $ENV{'host'} || $hostname || '127.0.0.1'; +my $peerport = $ENV{'port'} || '5038'; + +my $username = $ENV{'username'}; +my $secret = $ENV{'secret'}; + +my @CHANNELS = exists $ENV{'channels'} ? split ' ',$ENV{'channels'} : qw(Zap IAX2 SIP); +my @CODECS = exists $ENV{'codecs'} ? split ' ',$ENV{'codecs'} : qw(gsm ulaw alaw); +my @CODECSX = exists $ENV{'codecsx'} ? split ' ',$ENV{'codecsx'} : qw(0x2 0x4 0x8); + +my $meetme_enabled = $ENV{'enable_meetme'} || '0'; +my $confbridge_enabled = $ENV{'enable_confbridge'} || '1'; + +my $line, my $error; +my $socket = new IO::Socket::INET(PeerAddr => $peeraddr, + PeerPort => $peerport, + Proto => 'tcp') + or $error = "Could not create socket: $!"; + +if ( $socket ) { + # This will consume the "Asterisk Call Manager" welcome line. + $socket->getline; + + $socket->print("Action: login\nUsername: $username\nSecret: $secret\nEvents: off\n\n"); + my $response_status = $socket->getline; + + if ( $response_status !~ /^Response: Success\r?\n$/ ) { + my $response_message = $socket->getline; + $response_message =~ s/Message: (.*)\r?\n/$1/; + $error = "Asterisk authentication error: " . $response_message; + } + + while ( $line = $socket->getline and $line !~ /^\r?\n$/ ) {} +} + +if ( $ARGV[0] and $ARGV[0] eq 'autoconf' ) { + if ( $error ) { + print "no ($error)\n"; + } else { + print "yes\n"; + } + + exit 0; +} elsif ( $ARGV[0] and $ARGV[0] eq 'config' ) { + print "host_name $hostname" if $hostname; + + print <close(); + +my $active_channels = 'U'; +$active_channels = $1 if $channels_response =~ /\n([0-9]+) active channels?/; + +print < + +=head1 LICENSE + +Gnu GPLv2 + +=begin comment + +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 2 dated June, 1991. + +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. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +If you improve this script please send your version to my email +address with the copyright notice upgrade with your name. + +=end comment + +=head1 MAGIC MARKERS + + #%# family=contrib + +=cut + +# ################################################################################# +# Following example from current asterisk 1.4 +#> sip show peers +#Name/username Host Dyn Nat ACL Port Status +#104-RANDALLBUILT/104-RAND 74.218.176.166 D 5060 Unmonitored +#... +#102-ROCKSOLID/102-ROCKSOL (Unspecified) D 0 Unmonitored +#101-ROCKSOLID/101-ROCKSOL (Unspecified) D N 0 UNKNOWN +#20 sip peers [Monitored: 0 online, 1 offline Unmonitored: 2 online, 17 offline] +# ################################################################################# + +use IO::Socket; +use strict; + +if ($ARGV[0] and $ARGV[0] eq "config") +{ + print "graph_title Asterisk sip peers\n"; + print "graph_args --base 1000 -l 0\n"; + print "graph_order mon moff umon umoff\n"; + print "graph_vlabel peers\n"; + print "graph_category asterisk\n"; + #print "peers.label total\n"; + print "mon.draw AREA\n"; + print "mon.label monitored online\n"; + print "moff.draw STACK\n"; + print "moff.label monitored offline\n"; + print "umon.draw STACK\n"; + print "umon.label unmonitored online\n"; + print "umoff.draw STACK\n"; + print "umoff.label unmonitored offline\n"; + #graph_scale no + #load.warning 10 + #load.critical 120 + #graph_info The ... describes .... + #load.info Average load for the five minutes. + exit 0; +} + +my $host = exists $ENV{'host'} ? $ENV{'host'} : "127.0.0.1"; +my $port = exists $ENV{'port'} ? $ENV{'port'} : "5038"; + +my $username = $ENV{'username'}; +my $secret = $ENV{'secret'}; + +my $pop = new IO::Socket::INET (PeerAddr => $host, + PeerPort => $port, + Proto => 'tcp'); +die "Could not create socket: $!\n" unless $pop; + +## Read connection message. +my $line = $pop->getline; +die $line unless $line =~ /^Asterisk/; + +## Send user name. +$pop->print("Action: login\n"); +$pop->print("Username: $username\n"); +$pop->print("Secret: $secret\n"); +$pop->print("Events: off\n"); +$pop->print("\n"); + +while ($line = $pop->getline) +{ + last if $line eq "\r\n"; +} +#Response: Success +#Message: Authentication accepted + +## Request status of messages. +$pop->print("Action: command\n"); +$pop->print("Command: sip show peers\n"); +$pop->print("\n"); + +my ($peers,$monitor_online,$monitor_offline,$unmonitor_online,$unmonitor_offline)=(0,0,0,0,0); + +while (($line = $pop->getline) and ($line ne "\r\n")) +{ + $line =~ s/^Output: //; + my @fields = split(' ', $line); + my $count = @fields; + #20 sip peers [Monitored: 0 online, 1 offline Unmonitored: 2 online, 17 offline] + if (($count > 10) and ($fields[1] eq 'sip' and $fields[2] eq 'peers')) { + $peers = $fields[0]; + $monitor_online = $fields[4]; + $monitor_offline = $fields[6]; + $unmonitor_online = $fields[9]; + $unmonitor_offline = $fields[11]; + #print STDERR "$peers $monitor_online $monitor_offline $unmonitor_online $unmonitor_offline\n"; + last; + } +} + +$pop->print("Action: logoff\n"); +$pop->print("\n"); + +## Exhaust buffer before closing (to avoid polluting Asterisk's logs) +while ($line = $pop->getline) {} + +#print "peers.value $peers\n"; +print "mon.value $monitor_online\n"; +print "moff.value $monitor_offline\n"; +print "umon.value $unmonitor_online\n"; +print "umoff.value $unmonitor_offline\n"; + +# vim:syntax=perl