2011-05-04 Miguel de Dios <miguel.dedios@artica.es>

* util/pandora_xml_stress.pl: changed the source code to generate local conf
	for each agent. And in next executions you can change in remote conf in
	Pandora Console Enteprise as real agent.
	
	* util/pandora_xml_stress.README: added confs for the generate local conf.



git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@4300 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
mdtrooper 2011-05-04 10:50:19 +00:00
parent 6ac8529410
commit 7ddba9b5c1
3 changed files with 425 additions and 7 deletions

View File

@ -1,3 +1,11 @@
2011-05-04 Miguel de Dios <miguel.dedios@artica.es>
* util/pandora_xml_stress.pl: changed the source code to generate local conf
for each agent. And in next executions you can change in remote conf in
Pandora Console Enteprise as real agent.
* util/pandora_xml_stress.README: added confs for the generate local conf.
2011-05-04 Sergio Martin <sergio.martin@artica.es>
* util/pandora_manage.pl: Added standby field to be propagated

View File

@ -51,6 +51,14 @@ time_from 2009-06-01 00:00:00
# Data file generation end date, by default now.
time_to 2009-06-05 00:00:00
# Get and send the conf of agent from Pandora
get_and_send_agent_conf 1
# Directory of fake confs.
directory_confs .
# Directory of fake temp.
directory_temp /tmp
# Delay after generating the first data file for each agent to avoid
# race conditions when auto-creating the agent, by default 2.
startup_delay 2
@ -80,11 +88,14 @@ altitude_base 0
position_radius 10
# Address of the Tentacle server where XML files will be sent (optional).
# server_ip 192.168.50.1
#server_ip 127.0.0.1
# Port of the Tentacle server, by default 41121.
# server_port 41121
# Tentacle options.
#tentacle_options
# Module definitions. Similar to pandora_agent.conf.
module_begin

View File

@ -24,11 +24,13 @@ use threads::shared;
use Time::Local;
use Time::HiRes qw(gettimeofday);
use POSIX qw (strftime ceil);
use POSIX qw (strftime ceil floor);
use Data::Dumper;
use Math::Trig;
use File::Copy;
# Global variables used for statistics
my $Agents :shared = 0;
my $Modules :shared = 0;
@ -82,8 +84,8 @@ sub load_config ($\%\@) {
################################################################################
# Generate XML files.
################################################################################
sub generate_xml_files ($$$$$) {
my ($agents, $start, $step, $conf, $modules) = @_;
sub generate_xml_files ($$$$$$) {
my ($agents, $start, $step, $conf, $modules, $local_conf) = @_;
# Read agent configuration
my $interval = get_conf_token ($conf, 'agent_interval', '300');
@ -119,6 +121,12 @@ sub generate_xml_files ($$$$$) {
# Get the name of the agent
last unless defined ($agents->[$i]);
my $agent_name = $agents->[$i];
# Use the modules of local conf of agent.
if ($local_conf->{$agent_name}) {
$modules = $local_conf->{$agent_name};
}
# Agent random position
my $ag_latitude = $latitude_base + (rand ($position_radius) - $position_radius/2)/100;
my $ag_longitude = $longitude_base + (rand ($position_radius) - $position_radius/2)/100;
@ -130,8 +138,8 @@ sub generate_xml_files ($$$$$) {
my $sign = int rand(2);
$ag_timezone_offset += ($sign*(-1)+(1-$sign)) * int rand($ag_timezone_offset_range);
$xml_data .= "<agent_data os_name='$os_name' os_version='$os_version' interval='$interval' version='$os_version' timestamp='$timestamp' agent_name='$agent_name' timezone_offset='$ag_timezone_offset' longitude='$ag_longitude' latitude='$ag_latitude' altitude='$ag_altitude'>\n";
foreach my $module (@{$modules}) {
# Skip unnamed modules
my $module_name = get_conf_token ($module, 'module_name', '');
next if ($module_name eq '');
@ -214,6 +222,7 @@ sub generate_xml_files ($$$$$) {
$temporal .= $last_char if ($last_char ne '/');
# Save the XML data file
# The temporal dir is normaly the /var/spool/pandora/data_in
my $xml_file = $temporal . '/' . $agent_name . '_' . $utimestamp . '.data';
open (FILE, ">", $xml_file) || die ("[error] Could not write to '$xml_file': $!.\n\n");
print FILE $xml_data;
@ -375,6 +384,389 @@ sub log_message ($$) {
}
}
################################################################################
# INI MD5 FUNCTIONS
################################################################################
# Used to calculate the MD5 checksum of a string
use constant MOD232 => 2**32;
###############################################################################
# MD5 leftrotate function. See http://en.wikipedia.org/wiki/MD5#Pseudocode.
###############################################################################
sub leftrotate ($$) {
my ($x, $c) = @_;
return (0xFFFFFFFF & ($x << $c)) | ($x >> (32 - $c));
}
###############################################################################
# Initialize some variables needed by the MD5 algorithm.
# See http://en.wikipedia.org/wiki/MD5#Pseudocode.
###############################################################################
my (@R, @K);
sub md5_init () {
# R specifies the per-round shift amounts
@R = (7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21);
# Use binary integer part of the sines of integers (radians) as constants
for (my $i = 0; $i < 64; $i++) {
$K[$i] = floor(abs(sin($i + 1)) * MOD232);
}
}
###############################################################################
# Return the MD5 checksum of the given string.
# Pseudocode from http://en.wikipedia.org/wiki/MD5#Pseudocode.
###############################################################################
sub md5 ($) {
my $str = shift;
# Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating
# Initialize variables
my $h0 = 0x67452301;
my $h1 = 0xEFCDAB89;
my $h2 = 0x98BADCFE;
my $h3 = 0x10325476;
# Pre-processing
my $msg = unpack ("B*", pack ("A*", $str));
my $bit_len = length ($msg);
# Append "1" bit to message
$msg .= '1';
# Append "0" bits until message length in bits ≡ 448 (mod 512)
$msg .= '0' while ((length ($msg) % 512) != 448);
# Append bit /* bit, not byte */ length of unpadded message as 64-bit little-endian integer to message
$msg .= unpack ("B64", pack ("VV", $bit_len));
# Process the message in successive 512-bit chunks
for (my $i = 0; $i < length ($msg); $i += 512) {
my @w;
my $chunk = substr ($msg, $i, 512);
# Break chunk into sixteen 32-bit little-endian words w[i], 0 <= i <= 15
for (my $j = 0; $j < length ($chunk); $j += 32) {
push (@w, unpack ("V", pack ("B32", substr ($chunk, $j, 32))));
}
# Initialize hash value for this chunk
my $a = $h0;
my $b = $h1;
my $c = $h2;
my $d = $h3;
my $f;
my $g;
# Main loop
for (my $y = 0; $y < 64; $y++) {
if ($y <= 15) {
$f = $d ^ ($b & ($c ^ $d));
$g = $y;
}
elsif ($y <= 31) {
$f = $c ^ ($d & ($b ^ $c));
$g = (5 * $y + 1) % 16;
}
elsif ($y <= 47) {
$f = $b ^ $c ^ $d;
$g = (3 * $y + 5) % 16;
}
else {
$f = $c ^ ($b | (0xFFFFFFFF & (~ $d)));
$g = (7 * $y) % 16;
}
my $temp = $d;
$d = $c;
$c = $b;
$b = ($b + leftrotate (($a + $f + $K[$y] + $w[$g]) % MOD232, $R[$y])) % MOD232;
$a = $temp;
}
# Add this chunk's hash to result so far
$h0 = ($h0 + $a) % MOD232;
$h1 = ($h1 + $b) % MOD232;
$h2 = ($h2 + $c) % MOD232;
$h3 = ($h3 + $d) % MOD232;
}
# Digest := h0 append h1 append h2 append h3 #(expressed as little-endian)
return unpack ("H*", pack ("V", $h0)) . unpack ("H*", pack ("V", $h1)) . unpack ("H*", pack ("V", $h2)) . unpack ("H*", pack ("V", $h3));
}
################################################################################
# END MD5 FUNCTIONS
################################################################################
################################################################################
################################################################################
# Sends a file to the server.
################################################################################
sub send_file($$) {
my $file = shift;
my $conf = shift;printf($file . "\n");
my $output;
my $server_ip = get_conf_token($conf, 'server_ip', '');
my $server_port = get_conf_token($conf, 'server_port', '41121');
my $tentacle_options = get_conf_token($conf, 'tentacle_options', '');
# Shell command separator
my $CmdSep = ';';
# $DevNull
my $DevNull = '/dev/null';
$output = `tentacle_client -v -a $server_ip -p $server_port $tentacle_options $file 2>&1 >$DevNull`;
# Get the errorlevel
my $rc = $? >> 8;
if ($rc != 0) {
log_message($conf, "\tERROR:\tError sending file '$file': $output");
}
return $rc;
}
################################################################################
# Receive a file from the server.
################################################################################
sub recv_file ($$) {
my $file = shift;
my $conf = shift;
my $output;
my $directory_temp = get_conf_token($conf, 'directory_temp', '/tmp/');
my $server_ip = get_conf_token($conf, 'server_ip', '');
my $server_port = get_conf_token($conf, 'server_port', '41121');
my $tentacle_options = get_conf_token($conf, 'tentacle_options', '');
# Shell command separator
my $CmdSep = ';';
# $DevNull
my $DevNull = '/dev/null';
$output = `cd "$directory_temp"$CmdSep tentacle_client -v -g -a $server_ip -p $server_port $tentacle_options $file 2>&1 >$DevNull`;
# Get the errorlevel
my $rc;
$rc = $? >> 8;
if ($rc != 0) {
log_message ($conf, "\tERROR:\tGetting the remote $file.'\n");
log_message ($conf, "\tERROR:\t$output'\n");
}
return $rc;
}
################################################################################
################################################################################
# Get the send agent conf and generate modules.
################################################################################
sub get_and_send_agent_conf(\@\%\@\%) {
my ($agents, $conf, $modules, $local_conf) = @_;
my $get_and_send_agent_conf = get_conf_token($conf, 'get_and_send_agent_conf', '0');
my $directory_confs = get_conf_token($conf, 'directory_confs', '.');
my $directory_temp = get_conf_token($conf, 'directory_temp', '/tmp/');
my $md5_agent_name = '';
if ($get_and_send_agent_conf == 1) {
foreach my $agent (@{$agents}) {
$md5_agent_name = md5($agent);
if (open (CONF_FILE, "$directory_confs/$agent.conf")) {
binmode(CONF_FILE);
my $conf_md5 = md5 (join ('', <CONF_FILE>));
close (CONF_FILE);
# Get the remote MD5 file
if (recv_file("$md5_agent_name.md5", $conf) != 0) {
#The remote agent don't recive, then it send the agent conf and md5.
open (MD5_FILE, ">$directory_temp/$md5_agent_name.md5")
|| log_message ($conf, "\tERROR:\tCould not open file '$directory_temp/$md5_agent_name.md5' for writing: $!.");
print MD5_FILE $conf_md5;
close (MD5_FILE);
copy ("$directory_confs/$agent.conf", "$directory_temp/$md5_agent_name.conf");
send_file("$directory_temp/$md5_agent_name.conf", $conf);
send_file("$directory_temp/$md5_agent_name.md5", $conf);
log_message ($conf, "\tINFO:\tUploading configuration for the first time.");
unlink ("$directory_temp/$md5_agent_name.conf");
unlink ("$directory_temp/$md5_agent_name.md5");
}
else {
#There is a remote agent.
open (MD5_FILE, "< $directory_temp/$md5_agent_name.md5")
|| log_message ($conf, "Could not open file '$directory_confs/$md5_agent_name.md5' for writing: $!.");
#Get the first version of md5 file.
my $remote_conf_md5 = <MD5_FILE>;
close (MD5_FILE);
if ($remote_conf_md5 ne $conf_md5) {
if (recv_file ("$md5_agent_name.conf", $conf) != 0) {
log_message ($conf, "\tERROR:\t Get the remote '$agent.conf'.");
}
else {
move("$directory_temp/$md5_agent_name.conf", "$directory_confs/$agent.conf");
}
}
}
}
else {
log_message ($conf, "\tWARNING:\tThere is not the $agent.conf .'\n");
my $interval = get_conf_token($conf, 'agent_interval', '300');
my $timezone_offset = get_conf_token($conf, 'timezone_offset', '0');
my $module_txt = '';
my $temp = '';
# Create the block of modules.
foreach my $module (@{$modules}) {
$temp .= "
module_begin
module_name " . $module->{'module_name'} . "
module_type " . $module->{'module_type'} . "
module_exec " . $module->{'module_exec'} . "
module_min " . $module->{'module_min'} . "
module_max " . $module->{'module_max'} . "
module_end
";
}
my $default_conf =
"# General Parameters
# ==================
server_ip localhost
server_path /var/spool/pandora/data_in
temporal /tmp
logfile /var/log/pandora/pandora_agent.log
# Interval in seconds, 300 by default
interval $interval
# Debug mode only generate XML, and stop after first execution,
# and does not copy XML to server.
debug 0
# By default, agent takes machine name
agent_name $agent
# Agent description
description This conf is generated with pandora_xml_stress.
# Timezone offset: Difference with the server timezone
#timezone_offset $timezone_offset
# Listening TCP port for remote server. By default is 41121 (for tentacle)
# if you want to use SSH use 22, and FTP uses 21.
server_port 41121
# Transfer mode: tentacle, ftp, ssh or local
transfer_mode tentacle
# If set to 1 allows the agent to be configured via the web console (Only Enterprise version)
remote_config 1" . $temp;
if (open (CONF_FILE, ">$directory_confs/$agent.conf")) {
print CONF_FILE $default_conf;
close (CONF_FILE);
open (CONF_FILE, "$directory_confs/$agent.conf");
binmode(CONF_FILE);
my $conf_md5 = md5 (join ('', <CONF_FILE>));
close (CONF_FILE);
#Send files.
open (MD5_FILE, "> $directory_temp/$md5_agent_name.md5")
|| log_message ($conf, "\tERROR:\tCould not open file '$directory_temp/$agent.conf' for writing: $!.");
print MD5_FILE $conf_md5;
close (MD5_FILE);
copy ("$directory_confs/$agent.conf", "$directory_temp/$md5_agent_name.conf");
send_file ("$directory_temp/$md5_agent_name.conf", $conf);
send_file ("$directory_temp/$md5_agent_name.md5", $conf);
log_message ($conf, "\tINFO:\tUploading configuration for the first time.");
unlink ("$directory_temp/$md5_agent_name.conf");
unlink ("$directory_temp/$md5_agent_name.md5");
}
else {
log_message ($conf, "\ERROR:\tThe $agent.conf is not create.'\n");
}
}
# Fill the local conf for generate data
my $conf = parse_local_conf($agent, $conf);
$local_conf->{$agent} = $conf;
}
}
}
################################################################################
# Parse local conf.
################################################################################
sub parse_local_conf($$) {
my ($agent_name, $conf) = @_;
my $directory_confs = get_conf_token($conf, 'directory_confs', '.');
my @return;
if (open (CONF_FILE, "$directory_confs/$agent_name.conf")) {
my $line = '';
while (<CONF_FILE>) {
$line = $_;
# A module definition
if ($line =~ m/module_begin/) {
my %module;
# A comment
next if ($line =~ m/^#/);
while (my $line = <CONF_FILE>) {
# A comment
next if ($line =~ m/^#/);
last if ($line =~ m/module_end/);
# Unknown line
next if ($line !~ /^\s*(\w+)\s+(.+)$/);
$module{$1} = $2;
}
push(@return, \%module);
}
}
close (CONF_FILE);
}
else {
log_message ($conf, "\ERROR:\tOpen to parse the $agent_name.conf.'\n");
}
return \@return;
}
################################################################################
# Main
################################################################################
@ -402,14 +794,21 @@ while (my $agent_name = <FILE>) {
}
close (FILE);
# Init MD5
md5_init();
# Get the agent conf, instead use the conf in the pandora_xml_stress.conf
my %local_conf;
get_and_send_agent_conf(@agents, %conf, @modules, %local_conf);
# Get the maximum number of threads and the number of agents per thread
my $max_threads = 0 + get_conf_token (\%conf, 'max_threadss', '10');
my $max_threads = 0 + get_conf_token (\%conf, 'max_threads', '10');
my $step = ceil ($Agents / $max_threads);
my $t0 = gettimeofday ();
for (my $i = 0; $i < $Agents; $i += $step) {
threads->create (\&generate_xml_files, \@agents, $i, $step, \%conf, \@modules);
threads->create (\&generate_xml_files, \@agents, $i, $step, \%conf, \@modules, \%local_conf);
}
# Log some information for the user