summaryrefslogtreecommitdiffstats
path: root/admin/netsnmp-perl/haproxy.pl
diff options
context:
space:
mode:
Diffstat (limited to 'admin/netsnmp-perl/haproxy.pl')
-rw-r--r--admin/netsnmp-perl/haproxy.pl249
1 files changed, 249 insertions, 0 deletions
diff --git a/admin/netsnmp-perl/haproxy.pl b/admin/netsnmp-perl/haproxy.pl
new file mode 100644
index 0000000..64684ad
--- /dev/null
+++ b/admin/netsnmp-perl/haproxy.pl
@@ -0,0 +1,249 @@
+#
+# Net-SNMP perl plugin for HAProxy
+# Version 0.30
+#
+# Copyright 2007-2010 Krzysztof Piotr Oledzki <ole@ans.pl>
+#
+# 1. get a variable from "show stat":
+# 1.3.6.1.4.1.29385.106.1.$type.$field.$iid.$sid
+# type: 0->frontend, 1->backend, 2->server, 3->socket
+#
+# 2. get a variable from "show info":
+# 1.3.6.1.4.1.29385.106.2.$req.$varnr
+#
+# TODO:
+# - implement read timeout
+#
+
+use NetSNMP::agent (':all');
+use NetSNMP::ASN qw(:all);
+use IO::Socket::UNIX;
+
+use strict;
+
+my $agent = new NetSNMP::agent('Name' => 'HAProxy');
+my $sa = "/var/run/haproxy.stat";
+
+use constant OID_HAPROXY => '1.3.6.1.4.1.29385.106';
+use constant OID_HAPROXY_STATS => OID_HAPROXY . '.1';
+use constant OID_HAPROXY_INFO => OID_HAPROXY . '.2';
+
+my $oid_stat = new NetSNMP::OID(OID_HAPROXY_STATS);
+my $oid_info = new NetSNMP::OID(OID_HAPROXY_INFO);
+
+use constant STATS_PXNAME => 0;
+use constant STATS_SVNAME => 1;
+use constant STATS_IID => 27;
+use constant STATS_SID => 28;
+use constant STATS_TYPE => 32;
+
+use constant FIELD_INDEX => 10001;
+use constant FIELD_NAME => 10002;
+
+my %info_vars = (
+ 0 => 'Name',
+ 1 => 'Version',
+ 2 => 'Release_date',
+ 3 => 'Nbproc',
+ 4 => 'Process_num',
+ 5 => 'Pid',
+ 6 => 'Uptime',
+ 7 => 'Uptime_sec',
+ 8 => 'Memmax_MB',
+ 9 => 'Ulimit-n',
+ 10 => 'Maxsock',
+ 11 => 'Maxconn',
+ 12 => 'Maxpipes',
+ 13 => 'CurrConns',
+ 14 => 'PipesUsed',
+ 15 => 'PipesFree',
+ 16 => 'Tasks',
+ 17 => 'Run_queue',
+ 18 => 'node',
+ 19 => 'description',
+);
+
+sub find_next_stat_id {
+ my($type, $field, $proxyid, $sid) = @_;
+
+ my $obj = 1 << $type;
+
+ my $np = -1;
+ my $nl = -1;
+
+ my $sock = new IO::Socket::UNIX (Peer => $sa, Type => SOCK_STREAM, Timeout => 1);
+ next if !$sock;
+
+ print $sock "show stat -1 $obj -1\n";
+
+ while(<$sock>) {
+ chomp;
+ my @d = split(',');
+
+ last if !$d[$field] && $field != FIELD_INDEX && $field != FIELD_NAME && /^#/;
+ next if /^#/;
+
+ next if $d[STATS_TYPE] != $type;
+
+ next if ($d[STATS_IID] < $proxyid) || ($d[STATS_IID] == $proxyid && $d[STATS_SID] <= $sid);
+
+ if ($np == -1 || $d[STATS_IID] < $np || ($d[STATS_IID] == $np && $d[STATS_SID] < $nl)) {
+ $np = $d[STATS_IID];
+ $nl = $d[STATS_SID];
+ next;
+ }
+ }
+
+ close($sock);
+
+ return 0 if ($np == -1);
+
+ return "$type.$field.$np.$nl"
+}
+
+sub haproxy_stat {
+ my($handler, $registration_info, $request_info, $requests) = @_;
+
+ for(my $request = $requests; $request; $request = $request->next()) {
+ my $oid = $request->getOID();
+
+ $oid =~ s/$oid_stat//;
+ $oid =~ s/^\.//;
+
+ my $mode = $request_info->getMode();
+
+ my($type, $field, $proxyid, $sid, $or) = split('\.', $oid, 5);
+
+ next if $type > 3 || defined($or);
+
+ if ($mode == MODE_GETNEXT) {
+
+ $type = 0 if !$type;
+ $field = 0 if !$field;
+ $proxyid = 0 if !$proxyid;
+ $sid = 0 if !$sid;
+
+ my $nextid = find_next_stat_id($type, $field, $proxyid, $sid);
+ $nextid = find_next_stat_id($type, $field+1, 0, 0) if !$nextid;
+ $nextid = find_next_stat_id($type+1, 0, 0, 0) if !$nextid;
+
+ if ($nextid) {
+ ($type, $field, $proxyid, $sid) = split('\.', $nextid);
+ $request->setOID(sprintf("%s.%s", OID_HAPROXY_STATS, $nextid));
+ $mode = MODE_GET;
+ }
+ }
+
+ if ($mode == MODE_GET) {
+ next if !defined($proxyid) || !defined($type) || !defined($sid) || !defined($field);
+
+ my $obj = 1 << $type;
+
+ my $sock = new IO::Socket::UNIX (Peer => $sa, Type => SOCK_STREAM, Timeout => 1);
+ next if !$sock;
+
+ print $sock "show stat $proxyid $obj $sid\n";
+
+ while(<$sock>) {
+ chomp;
+ my @data = split(',');
+
+ last if !defined($data[$field]) && $field != FIELD_INDEX && $field != FIELD_NAME;
+
+ if ($proxyid) {
+ next if $data[STATS_IID] ne $proxyid;
+ next if $data[STATS_SID] ne $sid;
+ next if $data[STATS_TYPE] ne $type;
+ }
+
+ if ($field == FIELD_INDEX) {
+ $request->setValue(ASN_OCTET_STR,
+ sprintf("%s.%s", $data[STATS_IID],
+ $data[STATS_SID]));
+ } elsif ($field == FIELD_NAME) {
+ $request->setValue(ASN_OCTET_STR,
+ sprintf("%s/%s", $data[STATS_PXNAME],
+ $data[STATS_SVNAME]));
+ } else {
+ $request->setValue(ASN_OCTET_STR, $data[$field]);
+ }
+
+ close($sock);
+ last;
+ }
+
+ close($sock);
+ next;
+ }
+
+ }
+}
+
+sub haproxy_info {
+ my($handler, $registration_info, $request_info, $requests) = @_;
+
+ for(my $request = $requests; $request; $request = $request->next()) {
+ my $oid = $request->getOID();
+
+ $oid =~ s/$oid_info//;
+ $oid =~ s/^\.//;
+
+ my $mode = $request_info->getMode();
+
+ my($req, $nr, $or) = split('\.', $oid, 3);
+
+ next if $req >= 2 || defined($or);
+
+ if ($mode == MODE_GETNEXT) {
+ $req = 0 if !defined($req);
+ $nr = -1 if !defined($nr);
+
+ if (!defined($info_vars{$nr+1})) {
+ $req++;
+ $nr = -1;
+ }
+
+ next if $req >= 2;
+
+ $request->setOID(sprintf("%s.%s.%s", OID_HAPROXY_INFO, $req, ++$nr));
+ $mode = MODE_GET;
+
+ }
+
+ if ($mode == MODE_GET) {
+
+ next if !defined($req) || !defined($nr);
+
+ if ($req == 0) {
+ next if !defined($info_vars{$nr});
+ $request->setValue(ASN_OCTET_STR, $info_vars{$nr});
+ next;
+ }
+
+ if ($req == 1) {
+ next if !defined($info_vars{$nr});
+
+ my $sock = new IO::Socket::UNIX (Peer => $sa, Type => SOCK_STREAM, Timeout => 1);
+ next if !$sock;
+
+ print $sock "show info\n";
+
+ while(<$sock>) {
+ chomp;
+ my ($key, $val) = /(.*):\s*(.*)/;
+
+ next if $info_vars{$nr} ne $key;
+
+ $request->setValue(ASN_OCTET_STR, $val);
+ last;
+ }
+
+ close($sock);
+ }
+ }
+ }
+}
+
+$agent->register('HAProxy stat', OID_HAPROXY_STATS, \&haproxy_stat);
+$agent->register('HAProxy info', OID_HAPROXY_INFO, \&haproxy_info);
+