Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

executable file 221 lines (185 sloc) 6.151 kB
#! /usr/bin/perl
# Munin node that presents as many virtual hosts, plugins & fields
# as needed to be able to :
# - emulate a HUGE network to stress the munin-master server
# - serve as a basis for protocol debugging
#
# Copyright (C) 2010 Steve Schnepp under the GPLv2
use strict;
use warnings;
use IO::Socket;
use IO::Select;
use Getopt::Long;
# No buffering
$| = 1;
my $nb_servers = 3;
my $nb_plugins = 30;
my $fields_per_plugin = 5;
my $starting_port = 24949;
my $spoolfetch;
my $starting_epoch = -3600; # 1 hour from now
my $dump_config;
my $is_debug;
my $help;
my $update_rate = 10;
my $spoolfetch_rate = 5;
my $listen = "localhost";
my $arg_ret = GetOptions(
"nb-plugins|n=i" => \$nb_plugins,
"nb-fields|f=i" => \$fields_per_plugin,
"nb-servers|s=i" => \$nb_servers,
"update-rate=i" => \$update_rate,
"startint-port|p=i" => \$starting_port,
"listen=s" => \$listen,
"update-rate=i" => \$update_rate,
"spoolfetch" => \$spoolfetch,
"spoolfetch-rate=i" => \$spoolfetch_rate,
"starting-epoch=i" => \$starting_epoch,
"dump|d" => \$dump_config,
"help|h" => \$help,
"debug" => \$is_debug,
);
if ($help) {
print qq{Usage: $0 [options]
Options:
--help View this message.
-s --nb-servers <int> Number of servers [3]
-p --start-port <int> Starting TCP listening port [24949]
-n --nb-plugins <int> Number of plugins per server [30]
-f --nb-fields <int> Number of fields per plugins [5]
--update-rate <int> Update rate of plugins (in seconds) [10]
--listen <host> Which IP to bind [localhost].
Use '' or '*' to bind to every interface.
--spoolfetch Be spoolfetch capable
--starting-epoch Starting epoch: no data will available before.
Can be relative to now if negative [-3600]
-d --dump Only dump a generated munin.conf part [no]
--debug Print debug informations [no]
};
exit 0;
}
# Convert relatives starting_epoch to absolute
$starting_epoch = time + $starting_epoch if ($starting_epoch < 0);
if ($dump_config) {
for (my $i = 0; $i < $nb_servers; $i++) {
my $port = $starting_port + $i;
print "[host$port.debug.lan]\n";
print " address 127.0.0.1\n";
print " port $port\n";
print "\n";
}
# Only dump config
exit;
}
# start the servers
my @servers;
for (my $i = 0; $i < $nb_servers; $i ++) {
my $port = $starting_port + $i;
# LocalAddr == * doesn't work, it has to be empty
my $localaddr = ($listen eq '*') ? '' : $listen;
debug("starting server on port $listen:$port");
my $server = IO::Socket::INET->new(
"LocalPort" => $port,
"LocalAddr" => $localaddr,
"Listen" => 5,
"ReuseAddr" => 1,
"Proto" => "tcp",
) or die($!);
push @servers, $server;
}
# Ignoring SIG_CHILD
debug("Ignoring SIG_CHILD");
$SIG{CHLD} = 'IGNORE';
my $select = IO::Select->new(@servers);
while (my @ready = $select->can_read()) {
foreach my $ready_fh (@ready) {
my $client = $ready_fh->accept();
if (! fork()) {
debug("[$$] Serving new client");
service($client);
# Exit the child
debug("[$$] Finished");
exit;
}
}
}
sub service
{
my $client = shift;
my $hostname = "host".$client->sockport().".debug.lan";
print $client "# munin node at $hostname\n";
while (my $line = <$client>) {
chomp($line);
debug("[$$] client of $hostname asked : $line");
if ($line =~ m/^list /) {
for (my $i = 0; $i < $nb_plugins; $i ++) {
print $client "debug_plugin_$i ";
}
print $client "\n";
} elsif ($line =~ m/^cap (\w+)/) {
my @caps = "multigraph";
push @caps, "spool" if $spoolfetch;
print $client "cap @caps\n";
} elsif ($line =~ m/^config (\w+)/) {
my $plugin_number = get_plugin_number($1);
my $plugin_name = "debug_plugin_$plugin_number";
print $client "graph_title Debug plugin $plugin_number\n";
print $client "update_rate $update_rate\n";
for (my $i = 0; $i < $fields_per_plugin; $i ++) {
print $client "field_". $plugin_number . "_$i.label field $i of plugin $plugin_name on $hostname\n";
print $client "field_". $plugin_number . "_$i.type GAUGE\n";
}
print $client ".\n";
} elsif ($line =~ m/^fetch (\w+)/) {
my $plugin_number = get_plugin_number($1);
for (my $i = 0; $i < $fields_per_plugin; $i ++) {
my $value = sin( (time / 3600) * $plugin_number + $i);
print $client "field_". $plugin_number . "_$i.value $value\n";
}
print $client ".\n";
} elsif ($line =~ m/^spoolfetch (\d+)/) {
my $timestamp = $1;
# Cannot start before $starting_epoch
print "asked $timestamp, " if $is_debug;
$timestamp = ($timestamp < $starting_epoch) ? $starting_epoch : $timestamp;
print "starting at $starting_epoch, using $timestamp, \n" if $is_debug;
# Only send something every $spoolfetch_rate * $update_rate
if ( $timestamp > time - $spoolfetch_rate * $update_rate) {
print $client ".\n";
return;
}
# Sends spools strictly > LastSpooled
for (my $epoch = ($timestamp - $timestamp % $update_rate + $update_rate);
$epoch < time; $epoch += $update_rate) {
for (my $plugin_number = 0; $plugin_number < $nb_plugins; $plugin_number ++) {
my $plugin_name = "debug_plugin_$plugin_number";
print $client "multigraph $plugin_name\n";
print $client "graph_title Debug plugin $plugin_number\n";
print $client "update_rate $update_rate\n";
for (my $i = 0; $i < $fields_per_plugin; $i ++) {
print $client "field_". $plugin_number . "_$i.label field $i of plugin $plugin_name on $hostname\n";
print $client "field_".$plugin_number."_$i.type GAUGE\n";
my $value = sin( ($epoch / 3600) * $plugin_number + $i);
print $client "field_".$plugin_number."_$i.value $epoch:$value\n";
}
}
}
print $client ".\n";
} elsif ($line =~ m/^quit/) {
return;
} else {
print $client "# Command not found\n";
}
}
}
sub get_plugin_number
{
my $plugin_name = shift;
my $plugin_number = $1 if ($plugin_name =~ m/(\d+)/);
return $plugin_number;
}
sub debug
{
print join(" ", @_) . "\n" if $is_debug;
}
__END__
Jump to Line
Something went wrong with that request. Please try again.