Omnishell package
This commit is contained in:
parent
182df1c12d
commit
93938e902b
|
@ -33,6 +33,9 @@ use IO::Socket;
|
||||||
use Sys::Syslog;
|
use Sys::Syslog;
|
||||||
use Time::Local;
|
use Time::Local;
|
||||||
|
|
||||||
|
use lib '/usr/lib/perl5';
|
||||||
|
use PandoraFMS::Omnishell;
|
||||||
|
|
||||||
# Agent XML data
|
# Agent XML data
|
||||||
my $Xml;
|
my $Xml;
|
||||||
|
|
||||||
|
@ -43,7 +46,7 @@ my $Sem = undef;
|
||||||
my $ThreadSem = undef;
|
my $ThreadSem = undef;
|
||||||
|
|
||||||
use constant AGENT_VERSION => '7.0NG.749';
|
use constant AGENT_VERSION => '7.0NG.749';
|
||||||
use constant AGENT_BUILD => '200930';
|
use constant AGENT_BUILD => '201001';
|
||||||
|
|
||||||
# Agent log default file size maximum and instances
|
# Agent log default file size maximum and instances
|
||||||
use constant DEFAULT_MAX_LOG_SIZE => 600000;
|
use constant DEFAULT_MAX_LOG_SIZE => 600000;
|
||||||
|
@ -1058,8 +1061,6 @@ sub fix_directory ($) {
|
||||||
return $dir . $char;
|
return $dir . $char;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Sends a file to the server.
|
# Sends a file to the server.
|
||||||
################################################################################
|
################################################################################
|
||||||
|
@ -3079,8 +3080,11 @@ my $main_agent = -1;
|
||||||
# base time to start eatch iteration with the same interval.
|
# base time to start eatch iteration with the same interval.
|
||||||
my $iter_base_time = time();
|
my $iter_base_time = time();
|
||||||
$LogFileIdx = -1;
|
$LogFileIdx = -1;
|
||||||
|
|
||||||
# Loop
|
# Loop
|
||||||
while (1) {
|
while (1) {
|
||||||
|
my $omnishell;
|
||||||
|
|
||||||
if (-e $Conf{'logfile'} && (stat($Conf{'logfile'}))[7] > $Conf{'logsize'}) {
|
if (-e $Conf{'logfile'} && (stat($Conf{'logfile'}))[7] > $Conf{'logsize'}) {
|
||||||
rotate_log();
|
rotate_log();
|
||||||
}
|
}
|
||||||
|
@ -3095,15 +3099,17 @@ while (1) {
|
||||||
# Check file collections
|
# Check file collections
|
||||||
check_collections () unless ($Conf{'debug'} eq '1');
|
check_collections () unless ($Conf{'debug'} eq '1');
|
||||||
|
|
||||||
if ($Conf{'debug'} ne '1') {
|
eval {
|
||||||
# Check scheduled commands
|
# Omnishell controller.
|
||||||
my $omni = new PandoraFMS::Omnishell(\%Conf);
|
$omnishell = new PandoraFMS::Omnishell(
|
||||||
log_message('log', "Running omnishell process");
|
{
|
||||||
if (!$omni->run()) {
|
%Conf,
|
||||||
log_message('error', "Failed to run omnishell process: ".$omni->get_last_error());
|
'ConfDir' => $ConfDir
|
||||||
} else {
|
|
||||||
log_message('log', "Omnishell process completed.");
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
log_message('error', "Omnishell process error: ".$@);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Launch broker agents
|
# Launch broker agents
|
||||||
|
@ -3237,18 +3243,22 @@ while (1) {
|
||||||
|
|
||||||
if (ref ($Conf{'commands'}) eq "HASH") {
|
if (ref ($Conf{'commands'}) eq "HASH") {
|
||||||
foreach my $command (keys %{$Conf{'commands'}}) {
|
foreach my $command (keys %{$Conf{'commands'}}) {
|
||||||
my $result = evaluate_command($command);
|
eval {
|
||||||
if (ref($result) eq "HASH") {
|
if ($Conf{'debug'} eq '1') {
|
||||||
# Process command result.
|
log_message('debug', 'Running omnishell commmand ['.$command.']');
|
||||||
$Xml .= "<cmd_report>\n";
|
}
|
||||||
$Xml .= " <cmd_response>\n";
|
|
||||||
$Xml .= " <cmd_name><![CDATA[".$result->{'name'}."]]></cmd_name>\n";
|
my $output = $omnishell->run($command, 'xml');
|
||||||
$Xml .= " <cmd_key><![CDATA[".$command."]]></cmd_key>\n";
|
if (!empty($output)) {
|
||||||
$Xml .= " <cmd_errorlevel><![CDATA[".$result->{'error_level'}."]]></cmd_errorlevel>\n";
|
$Xml .= $output;
|
||||||
$Xml .= " <cmd_stdout><![CDATA[".$result->{'stdout'}."]]></cmd_stdout>\n";
|
} else {
|
||||||
$Xml .= " <cmd_stderr><![CDATA[".$result->{'stderr'}."]]></cmd_stderr>\n";
|
if ($Conf{'debug'} eq '1') {
|
||||||
$Xml .= " </cmd_response>\n";
|
log_message('error', 'Omnishell result: '.$omnishell->get_last_error());
|
||||||
$Xml .= "</cmd_report>\n";
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
log_message('error', 'Omnishell error: '.$@);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,11 @@ package PandoraFMS::Omnishell;
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
|
use File::Copy;
|
||||||
|
use Scalar::Util qw(looks_like_number);
|
||||||
|
use lib '/usr/lib/perl5';
|
||||||
|
use PandoraFMS::PluginTools qw/init read_configuration read_file empty trim/;
|
||||||
|
|
||||||
my $YAML = 0;
|
my $YAML = 0;
|
||||||
# Dynamic load. Avoid unwanted behaviour.
|
# Dynamic load. Avoid unwanted behaviour.
|
||||||
eval {
|
eval {
|
||||||
|
@ -26,6 +31,137 @@ our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
|
||||||
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
||||||
our @EXPORT = qw();
|
our @EXPORT = qw();
|
||||||
|
|
||||||
|
# 2 to the power of 32.
|
||||||
|
use constant POW232 => 2**32;
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Return the MD5 checksum of the given string as a hex string.
|
||||||
|
# Pseudocode from: http://en.wikipedia.org/wiki/MD5#Pseudocode
|
||||||
|
################################################################################
|
||||||
|
my @S = (
|
||||||
|
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
|
||||||
|
);
|
||||||
|
my @K = (
|
||||||
|
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||||
|
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||||
|
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||||
|
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||||
|
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||||
|
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||||
|
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||||
|
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||||
|
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||||
|
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||||
|
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||||
|
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||||
|
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||||
|
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||||
|
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||||
|
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
|
||||||
|
);
|
||||||
|
sub md5 {
|
||||||
|
my $str = shift;
|
||||||
|
|
||||||
|
# No input!
|
||||||
|
if (!defined($str)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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 ("B32", pack ("V", $bit_len));
|
||||||
|
$msg .= unpack ("B32", pack ("V", ($bit_len >> 16) >> 16));
|
||||||
|
|
||||||
|
# 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]) % POW232, $S[$y])) % POW232;
|
||||||
|
$a = $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add this chunk's hash to result so far.
|
||||||
|
$h0 = ($h0 + $a) % POW232;
|
||||||
|
$h1 = ($h1 + $b) % POW232;
|
||||||
|
$h2 = ($h2 + $c) % POW232;
|
||||||
|
$h3 = ($h3 + $d) % POW232;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# MD5 leftrotate function. See: http://en.wikipedia.org/wiki/MD5#Pseudocode
|
||||||
|
################################################################################
|
||||||
|
sub leftrotate {
|
||||||
|
my ($x, $c) = @_;
|
||||||
|
|
||||||
|
return (0xFFFFFFFF & ($x << $c)) | ($x >> (32 - $c));
|
||||||
|
}
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# return last error.
|
# return last error.
|
||||||
|
@ -33,13 +169,22 @@ our @EXPORT = qw();
|
||||||
sub get_last_error {
|
sub get_last_error {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
if (!is_empty($self->{'last_error'})) {
|
if (!empty($self->{'last_error'})) {
|
||||||
return $self->{'last_error'};
|
return $self->{'last_error'};
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Update last error.
|
||||||
|
################################################################################
|
||||||
|
sub set_last_error {
|
||||||
|
my ($self, $error) = @_;
|
||||||
|
|
||||||
|
$self->{'last_error'} = $error;
|
||||||
|
}
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Try to load extra libraries.c
|
# Try to load extra libraries.c
|
||||||
################################################################################
|
################################################################################
|
||||||
|
@ -60,19 +205,21 @@ sub load_libraries {
|
||||||
# Create new omnishell handler.
|
# Create new omnishell handler.
|
||||||
################################################################################
|
################################################################################
|
||||||
sub new {
|
sub new {
|
||||||
my ($class,$args) = @_;
|
my ($class, $args) = @_;
|
||||||
|
|
||||||
if (ref($args) ne 'HASH') {
|
if (ref($args) ne 'HASH') {
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $system = init();
|
||||||
my $self = {
|
my $self = {
|
||||||
'last_error' => undef,
|
'last_error' => undef,
|
||||||
%{$args}
|
%{$system},
|
||||||
|
%{$args},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
$self = bless($self, $class);
|
$self = bless($self, $class);
|
||||||
|
$self->prepare_commands();
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
@ -81,11 +228,35 @@ sub new {
|
||||||
# Run process.
|
# Run process.
|
||||||
################################################################################
|
################################################################################
|
||||||
sub run {
|
sub run {
|
||||||
my ($self) = @_;
|
my ($self, $ref, $output_mode) = @_;
|
||||||
|
|
||||||
if($self->load_libraries()) {
|
if($self->load_libraries()) {
|
||||||
$self->prepare_commands();
|
# Functionality possible.
|
||||||
|
my $command = $self->{'commands'}->{$ref};
|
||||||
|
my $result = $self->evaluate_command($ref);
|
||||||
|
if (ref($result) eq "HASH") {
|
||||||
|
# Process command result.
|
||||||
|
if (defined($output_mode) && $output_mode eq 'xml') {
|
||||||
|
my $output = '';
|
||||||
|
$output .= "<cmd_report>\n";
|
||||||
|
$output .= " <cmd_response>\n";
|
||||||
|
$output .= " <cmd_name><![CDATA[".$result->{'name'}."]]></cmd_name>\n";
|
||||||
|
$output .= " <cmd_key><![CDATA[".$ref."]]></cmd_key>\n";
|
||||||
|
$output .= " <cmd_errorlevel><![CDATA[".$result->{'error_level'}."]]></cmd_errorlevel>\n";
|
||||||
|
$output .= " <cmd_stdout><![CDATA[".$result->{'stdout'}."]]></cmd_stdout>\n";
|
||||||
|
$output .= " <cmd_stderr><![CDATA[".$result->{'stderr'}."]]></cmd_stderr>\n";
|
||||||
|
$output .= " </cmd_response>\n";
|
||||||
|
$output .= "</cmd_report>\n";
|
||||||
|
|
||||||
|
return $output;
|
||||||
}
|
}
|
||||||
|
return $result;
|
||||||
|
} else {
|
||||||
|
$self->set_last_error('Failed to process ['.$ref.']: '.$result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
@ -95,45 +266,35 @@ sub prepare_commands {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
if ($YAML == 0) {
|
if ($YAML == 0) {
|
||||||
log_message(
|
$self->set_last_error('Cannot use commands without YAML dependency, please install it.');
|
||||||
'error',
|
|
||||||
'Cannot use commands without YAML dependency, please install it.'
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Force configuration file read.
|
# Force configuration file read.
|
||||||
my @commands = read_config('cmd_file');
|
my $commands = $self->{'commands'};
|
||||||
|
|
||||||
if (empty(\@commands)) {
|
if (empty($commands)) {
|
||||||
$self->{'commands'} = {};
|
$self->{'commands'} = {};
|
||||||
} else {
|
} else {
|
||||||
foreach my $rcmd (@commands) {
|
foreach my $rcmd (keys %{$commands}) {
|
||||||
$self->{'commands'}->{trim($rcmd)} = {};
|
$self->{'commands'}->{trim($rcmd)} = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Cleanup old commands. Not registered.
|
# Cleanup old commands. Not registered.
|
||||||
cleanup_old_commands();
|
$self->cleanup_old_commands();
|
||||||
|
|
||||||
foreach my $ref (keys %{$self->{'commands'}}) {
|
foreach my $ref (keys %{$self->{'commands'}}) {
|
||||||
my $file_content;
|
my $file_content;
|
||||||
my $download = 0;
|
my $download = 0;
|
||||||
my $rcmd_file = $self->{'ConfDir'}.'/commands/'.$ref.'.rcmd';
|
my $rcmd_file = $self->{'ConfDir'}.'/commands/'.$ref.'.rcmd';
|
||||||
|
|
||||||
# Check for local .rcmd.done files
|
|
||||||
if (-e $rcmd_file.'.done') {
|
|
||||||
# Ignore.
|
|
||||||
delete $self->{'commands'}->{$ref};
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Search for local .rcmd file
|
# Search for local .rcmd file
|
||||||
if (-e $rcmd_file) {
|
if (-e $rcmd_file) {
|
||||||
my $remote_md5_file = $self->{'temporal'}.'/'.$ref.'.md5';
|
my $remote_md5_file = $self->{'temporal'}.'/'.$ref.'.md5';
|
||||||
|
|
||||||
$file_content = read_file($rcmd_file);
|
$file_content = read_file($rcmd_file);
|
||||||
if (recv_file($ref.'.md5', $remote_md5_file) != 0) {
|
if ($self->recv_file($ref.'.md5', $remote_md5_file) != 0) {
|
||||||
# Remote file could not be retrieved, skip.
|
# Remote file could not be retrieved, skip.
|
||||||
delete $self->{'commands'}->{$ref};
|
delete $self->{'commands'}->{$ref};
|
||||||
next;
|
next;
|
||||||
|
@ -153,7 +314,7 @@ sub prepare_commands {
|
||||||
# Search for remote .rcmd file
|
# Search for remote .rcmd file
|
||||||
if ($download == 1) {
|
if ($download == 1) {
|
||||||
# Download .rcmd file
|
# Download .rcmd file
|
||||||
if (recv_file($ref.'.rcmd') != 0) {
|
if ($self->recv_file($ref.'.rcmd') != 0) {
|
||||||
# Remote file could not be retrieved, skip.
|
# Remote file could not be retrieved, skip.
|
||||||
delete $self->{'commands'}->{$ref};
|
delete $self->{'commands'}->{$ref};
|
||||||
next;
|
next;
|
||||||
|
@ -169,7 +330,7 @@ sub prepare_commands {
|
||||||
};
|
};
|
||||||
if ($@) {
|
if ($@) {
|
||||||
# Failed.
|
# Failed.
|
||||||
log_message('error', 'Failed to decode command. ' . "\n".$@);
|
$self->set_last_error('Failed to decode command. ' . "\n".$@);
|
||||||
delete $self->{'commands'}->{$ref};
|
delete $self->{'commands'}->{$ref};
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +359,7 @@ sub report_command {
|
||||||
$return->{'name'} = $self->{'commands'}->{$ref}->[0]->{'name'};
|
$return->{'name'} = $self->{'commands'}->{$ref}->[0]->{'name'};
|
||||||
};
|
};
|
||||||
if ($@) {
|
if ($@) {
|
||||||
log_message('error', 'Failed to report command output. ' . $@);
|
$self->set_last_error('Failed to report command output. ' . $@);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
|
@ -252,7 +413,7 @@ sub cleanup_old_commands {
|
||||||
# Executes a command using defined timeout.
|
# Executes a command using defined timeout.
|
||||||
################################################################################
|
################################################################################
|
||||||
sub execute_command_timeout {
|
sub execute_command_timeout {
|
||||||
my ($cmd, $timeout) = @_;
|
my ($self, $cmd, $timeout) = @_;
|
||||||
|
|
||||||
if (!defined($timeout)
|
if (!defined($timeout)
|
||||||
|| !looks_like_number($timeout)
|
|| !looks_like_number($timeout)
|
||||||
|
@ -270,7 +431,7 @@ sub execute_command_timeout {
|
||||||
my $pid = open ($RET, "-|");
|
my $pid = open ($RET, "-|");
|
||||||
if (!defined($pid)) {
|
if (!defined($pid)) {
|
||||||
# Failed to fork.
|
# Failed to fork.
|
||||||
log_message('error', '[command] Failed to fork.');
|
$self->set_last_error('[command] Failed to fork.');
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
if ($pid == 0) {
|
if ($pid == 0) {
|
||||||
|
@ -322,7 +483,7 @@ sub execute_command_timeout {
|
||||||
# $std_files = ' >> /tmp/stdout 2>> /tmp/stderr
|
# $std_files = ' >> /tmp/stdout 2>> /tmp/stderr
|
||||||
################################################################################
|
################################################################################
|
||||||
sub execute_command_block {
|
sub execute_command_block {
|
||||||
my ($commands, $std_files, $timeout, $retry) = @_;
|
my ($self, $commands, $std_files, $timeout, $retry) = @_;
|
||||||
|
|
||||||
return 0 unless defined($commands);
|
return 0 unless defined($commands);
|
||||||
|
|
||||||
|
@ -337,7 +498,7 @@ sub execute_command_block {
|
||||||
return 0 if $commands eq '';
|
return 0 if $commands eq '';
|
||||||
|
|
||||||
do {
|
do {
|
||||||
$err_level = execute_command_timeout(
|
$err_level = $self->execute_command_timeout(
|
||||||
"($commands) $std_files",
|
"($commands) $std_files",
|
||||||
$timeout
|
$timeout
|
||||||
);
|
);
|
||||||
|
@ -353,7 +514,7 @@ sub execute_command_block {
|
||||||
$retries = 1 unless looks_like_number($retries) && $retries > 0;
|
$retries = 1 unless looks_like_number($retries) && $retries > 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
$err_level = execute_command_timeout(
|
$err_level = $self->execute_command_timeout(
|
||||||
"($comm) $std_files",
|
"($comm) $std_files",
|
||||||
$timeout
|
$timeout
|
||||||
);
|
);
|
||||||
|
@ -378,10 +539,10 @@ sub evaluate_command {
|
||||||
my ($self, $ref) = @_;
|
my ($self, $ref) = @_;
|
||||||
|
|
||||||
# Not found.
|
# Not found.
|
||||||
return unless defined $self->{'commands'}->{$ref};
|
return "undefined command" unless defined $self->{'commands'}->{$ref};
|
||||||
|
|
||||||
# Already completed.
|
# Already completed.
|
||||||
return if (-e $self->{'ConfDir'}.'/commands/'.$ref.'.rcmd.done');
|
return "already executed" if (-e $self->{'ConfDir'}.'/commands/'.$ref.'.rcmd.done');
|
||||||
|
|
||||||
# [0] because how library works.
|
# [0] because how library works.
|
||||||
my $cmd = $self->{'commands'}->{$ref}->[0];
|
my $cmd = $self->{'commands'}->{$ref}->[0];
|
||||||
|
@ -392,34 +553,113 @@ sub evaluate_command {
|
||||||
# Check preconditions
|
# Check preconditions
|
||||||
my $err_level;
|
my $err_level;
|
||||||
|
|
||||||
$err_level = execute_command_block(
|
$err_level = $self->execute_command_block(
|
||||||
$cmd->{'preconditions'},
|
$cmd->{'preconditions'},
|
||||||
$std_files,
|
$std_files,
|
||||||
$cmd->{'timeout'}
|
$cmd->{'timeout'}
|
||||||
);
|
);
|
||||||
|
|
||||||
# Precondition not satisfied.
|
# Precondition not satisfied.
|
||||||
return report_command($ref, $err_level) unless ($err_level == 0);
|
return $self->report_command($ref, $err_level) unless ($err_level == 0);
|
||||||
|
|
||||||
# Main run.
|
# Main run.
|
||||||
$err_level = execute_command_block(
|
$err_level = $self->execute_command_block(
|
||||||
$cmd->{'script'},
|
$cmd->{'script'},
|
||||||
$std_files,
|
$std_files,
|
||||||
$cmd->{'timeout'}
|
$cmd->{'timeout'}
|
||||||
);
|
);
|
||||||
|
|
||||||
# Script not success.
|
# Script not success.
|
||||||
return report_command($ref, $err_level) unless ($err_level == 0);
|
return $self->report_command($ref, $err_level) unless ($err_level == 0);
|
||||||
|
|
||||||
# Check postconditions
|
# Check postconditions
|
||||||
$err_level = execute_command_block(
|
$err_level = $self->execute_command_block(
|
||||||
$cmd->{'postconditions'},
|
$cmd->{'postconditions'},
|
||||||
$std_files,
|
$std_files,
|
||||||
$cmd->{'timeout'}
|
$cmd->{'timeout'}
|
||||||
);
|
);
|
||||||
|
|
||||||
# Return results.
|
# Return results.
|
||||||
return report_command($ref, $err_level);
|
return $self->report_command($ref, $err_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# File transference and imported methods
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
## Remove any trailing / from directory names.
|
||||||
|
################################################################################
|
||||||
|
sub fix_directory ($) {
|
||||||
|
my $dir = shift;
|
||||||
|
|
||||||
|
my $char = chop($dir);
|
||||||
|
return $dir if ($char eq '/');
|
||||||
|
return $dir . $char;
|
||||||
|
}
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Receive a file from the server.
|
||||||
|
################################################################################
|
||||||
|
sub recv_file {
|
||||||
|
my ($self, $file, $relative) = @_;
|
||||||
|
my $output;
|
||||||
|
|
||||||
|
my $DevNull = $self->{'__system'}->{'devnull'};
|
||||||
|
my $CmdSep = $self->{'__system'}->{'cmdsep'};
|
||||||
|
|
||||||
|
my $pid = fork();
|
||||||
|
return 1 unless defined $pid;
|
||||||
|
|
||||||
|
# Fix remote dir to some transfer mode
|
||||||
|
my $remote_dir = $self->{'server_path'};
|
||||||
|
$remote_dir .= "/" . fix_directory($relative) if defined($relative);
|
||||||
|
|
||||||
|
if ($pid == 0) {
|
||||||
|
# execute the transfer program by child process.
|
||||||
|
eval {
|
||||||
|
local $SIG{'ALRM'} = sub {die};
|
||||||
|
alarm ($self->{'transfer_timeout'});
|
||||||
|
if ($self->{'transfer_mode'} eq 'tentacle') {
|
||||||
|
$output = `cd "$self->{'temporal'}"$CmdSep tentacle_client -v -g -a $self->{'server_ip'} -p $self->{'server_port'} $self->{'server_opts'} $file 2>&1 >$DevNull`
|
||||||
|
} elsif ($self->{'transfer_mode'} eq 'ssh') {
|
||||||
|
$output = `scp -P $self->{'server_port'} pandora@"$self->{'server_ip'}:$self->{'server_path'}/$file" $self->{'temporal'} 2>&1 >$DevNull`;
|
||||||
|
} elsif ($self->{'transfer_mode'} eq 'ftp') {
|
||||||
|
my $base = basename ($file);
|
||||||
|
my $dir = dirname ($file);
|
||||||
|
|
||||||
|
$output = `ftp -n $self->{'server_opts'} $self->{'server_ip'} $self->{'server_port'} 2>&1 >$DevNull <<FEOF1
|
||||||
|
quote USER $self->{'server_user'}
|
||||||
|
quote PASS $self->{'server_pwd'}
|
||||||
|
lcd "$self->{'temporal'}"
|
||||||
|
cd "$self->{'server_path'}"
|
||||||
|
get "$file"
|
||||||
|
quit
|
||||||
|
FEOF1`
|
||||||
|
} elsif ($self->{'transfer_mode'} eq 'local') {
|
||||||
|
$output = `cp "$remote_dir/$file" $self->{'temporal'} 2>&1 >$DevNull`;
|
||||||
|
}
|
||||||
|
alarm (0);
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($@) {
|
||||||
|
$self->set_last_error("Error retrieving file: '.$file.' File transfer command is not responding.");
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the errorlevel
|
||||||
|
my $rc = $? >> 8;
|
||||||
|
if ($rc != 0) {
|
||||||
|
$self->set_last_error("Error retrieving file: '$file' $output");
|
||||||
|
}
|
||||||
|
exit $rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wait the child process termination and get the errorlevel
|
||||||
|
waitpid ($pid, 0);
|
||||||
|
my $rc = $? >> 8;
|
||||||
|
|
||||||
|
return $rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
1;
|
1;
|
|
@ -1165,6 +1165,7 @@ sub init_system {
|
||||||
$system{echo} = "echo";
|
$system{echo} = "echo";
|
||||||
$system{wcl} = "wc -l";
|
$system{wcl} = "wc -l";
|
||||||
$system{tmp} = ".\\";
|
$system{tmp} = ".\\";
|
||||||
|
$system{cmdsep} = "\&";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$system{devnull} = "/dev/null";
|
$system{devnull} = "/dev/null";
|
||||||
|
@ -1175,6 +1176,7 @@ sub init_system {
|
||||||
$system{echo} = "echo";
|
$system{echo} = "echo";
|
||||||
$system{wcl} = "wc -l";
|
$system{wcl} = "wc -l";
|
||||||
$system{tmp} = "/tmp";
|
$system{tmp} = "/tmp";
|
||||||
|
$system{cmdsep} = ";";
|
||||||
|
|
||||||
if ($^O =~ /hpux/i) {
|
if ($^O =~ /hpux/i) {
|
||||||
$system{os} = "HPUX";
|
$system{os} = "HPUX";
|
||||||
|
|
Loading…
Reference in New Issue