WIP
This commit is contained in:
Quentin Garnier 2014-10-20 17:24:58 +02:00
parent 8479952a1a
commit 92db819eae
4 changed files with 452 additions and 329 deletions

View File

@ -9,7 +9,6 @@ sub new {
my $class = shift;
my $self = {};
$self->{logger} = shift;
$self->{obj_esxd} = shift;
$self->{commandName} = 'healthhost';
bless $self, $class;
@ -22,26 +21,38 @@ sub getCommandName {
}
sub checkArgs {
my $self = shift;
my ($host) = @_;
my ($self, %options) = @_;
if (!defined($host) || $host eq "") {
$self->{logger}->writeLogError("ARGS error: need hostname");
if (!defined($options{arguments}->{esx_hostname}) || $options{arguments}->{esx_hostname} eq "") {
$options{manager}->{output}->output_add(severity => 'UNKNOWN',
short_msg => "Argument error: need esx hostname");
return 1;
}
return 0;
}
sub initArgs {
my $self = shift;
$self->{lhost} = $_[0];
$self->{storage_status} = (defined($_[1]) && $_[1] == 1) ? 1 : 0;
my ($self, %options) = @_;
foreach (keys %{$options{arguments}}) {
$self->{$_} = $options{arguments}->{$_};
}
$self->{manager} = centreon::esxd::common::init_response();
$self->{manager}->{output}->{plugin} = $options{arguments}->{identity};
$self->{manager}->{perfdata}->threshold_validate(label => 'warning', value => 0);
$self->{manager}->{perfdata}->threshold_validate(label => 'critical', value => 0);
}
sub set_connector {
my ($self, %options) = @_;
$self->{obj_esxd} = $options{connector};
}
sub run {
my $self = shift;
my %filters = ('name' => $self->{lhost});
my %filters = (name => $self->{esx_hostname});
my @properties = ('runtime.healthSystemRuntime.hardwareStatusInfo', 'runtime.healthSystemRuntime.systemHealthInfo.numericSensorInfo',
'runtime.connectionState');
my $result = centreon::esxd::common::get_entities_host($self->{obj_esxd}, 'HostSystem', \%filters, \@properties);
@ -49,20 +60,13 @@ sub run {
return ;
}
return if (centreon::esxd::common::host_state($self->{obj_esxd}, $self->{lhost},
return if (centreon::esxd::common::host_state($self->{obj_esxd}, $self->{esx_hostname},
$$result[0]->{'runtime.connectionState'}->val) == 0);
my $status = 0; # OK
my $output_critical = '';
my $output_critical_append = '';
my $output_warning = '';
my $output_warning_append = '';
my $output = '';
my $output_append = '';
my $OKCount = 0;
my $CAlertCount = 0;
my $WAlertCount = 0;
foreach my $entity_view (@$result) {
my $OKCount = 0;
my $CAlertCount = 0;
my $WAlertCount = 0;
my $cpuStatusInfo = $entity_view->{'runtime.healthSystemRuntime.hardwareStatusInfo'}->{cpuStatusInfo};
my $memoryStatusInfo = $entity_view->{'runtime.healthSystemRuntime.hardwareStatusInfo'}->{memoryStatusInfo};
my $storageStatusInfo = $entity_view->{'runtime.healthSystemRuntime.hardwareStatusInfo'}->{storageStatusInfo};
@ -72,14 +76,10 @@ sub run {
if (defined($cpuStatusInfo)) {
foreach (@$cpuStatusInfo) {
if ($_->status->key =~ /^red$/i) {
centreon::esxd::common::output_add(\$output_critical, \$output_critical_append, ", ",
$_->name . ": " . $_->status->summary);
$status = centreon::esxd::common::errors_mask($status, 'CRITICAL');
$self->{manager}->{output}->output_add(long_msg => $_->name . ": " . $_->status->summary);
$CAlertCount++;
} elsif ($_->status->key =~ /^yellow$/i) {
centreon::esxd::common::output_add(\$output_warning, \$output_warning_append, ", ",
$_->name . ": " . $_->status->summary);
$status = centreon::esxd::common::errors_mask($status, 'WARNING');
$self->{manager}->{output}->output_add(long_msg => $_->name . ": " . $_->status->summary);
$WAlertCount++;
} else {
$OKCount++;
@ -91,14 +91,10 @@ sub run {
if (defined($memoryStatusInfo)) {
foreach (@$memoryStatusInfo) {
if ($_->status->key =~ /^red$/i) {
centreon::esxd::common::output_add(\$output_critical, \$output_critical_append, ", ",
$_->name . ": " . $_->status->summary);
$status = centreon::esxd::common::errors_mask($status, 'CRITICAL');
$self->{manager}->{output}->output_add(long_msg => $_->name . ": " . $_->status->summary);
$CAlertCount++;
} elsif ($_->status->key =~ /^yellow$/i) {
centreon::esxd::common::output_add(\$output_warning, \$output_warning_append, ", ",
$_->name . ": " . $_->status->summary);
$status = centreon::esxd::common::errors_mask($status, 'WARNING');
$self->{manager}->{output}->output_add(long_msg => $_->name . ": " . $_->status->summary);
$WAlertCount++;
} else {
$OKCount++;
@ -110,14 +106,10 @@ sub run {
if ($self->{storage_status} == 1 && defined($storageStatusInfo)) {
foreach (@$storageStatusInfo) {
if ($_->status->key =~ /^red$/i) {
centreon::esxd::common::output_add(\$output_critical, \$output_critical_append, ", ",
$_->name . ": " . $_->status->summary);
$status = centreon::esxd::common::errors_mask($status, 'CRITICAL');
$self->{manager}->{output}->output_add(long_msg => $_->name . ": " . $_->status->summary);
$CAlertCount++;
} elsif ($_->status->key =~ /^yellow$/i) {
centreon::esxd::common::output_add(\$output_warning, \$output_warning_append, ", ",
$_->name . ": " . $_->status->summary);
$status = centreon::esxd::common::errors_mask($status, 'WARNING');
$self->{manager}->{output}->output_add(long_msg => $_->name . ": " . $_->status->summary);
$WAlertCount++;
} else {
$OKCount++;
@ -129,34 +121,32 @@ sub run {
if (defined($numericSensorInfo)) {
foreach (@$numericSensorInfo) {
if ($_->healthState->key =~ /^red$/i) {
centreon::esxd::common::output_add(\$output_critical, \$output_critical_append, ", ",
$_->sensorType . " sensor " . $_->name . ": ".$_->healthState->summary);
$status = centreon::esxd::common::errors_mask($status, 'CRITICAL');
$self->{manager}->{output}->output_add(long_msg => $_->sensorType . " sensor " . $_->name . ": ".$_->healthState->summary);
$CAlertCount++;
} elsif ($_->healthState->key =~ /^yellow$/i) {
centreon::esxd::common::output_add(\$output_warning, \$output_warning_append, ", ",
$_->sensorType . " sensor " . $_->name . ": ".$_->healthState->summary);
$status = centreon::esxd::common::errors_mask($status, 'WARNING');
$self->{manager}->{output}->output_add(long_msg => $_->sensorType . " sensor " . $_->name . ": ".$_->healthState->summary);
$WAlertCount++;
} else {
$OKCount++;
}
}
}
my $exit = $self->{manager}->{perfdata}->threshold_check(value => $WAlertCount,
threshold => [ { label => 'warning', exit_litteral => 'warning' } ]);
if (!$self->{manager}->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{manager}->{output}->output_add(severity => $exit,
short_msg => sprintf("%s health issue(s) found", $WAlertCount));
}
$exit = $self->{manager}->{perfdata}->threshold_check(value => $CAlertCount, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' } ]);
if (!$self->{manager}->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{manager}->{output}->output_add(severity => $exit,
short_msg => sprintf("%s health issue(s) found", $CAlertCount));
}
$self->{manager}->{output}->output_add(severity => 'OK',
short_msg => sprintf("All %s health checks are green", $OKCount));
}
if ($output_critical ne "") {
$output .= $output_append . "CRITICAL - $CAlertCount health issue(s) found: $output_critical";
$output_append = ". ";
}
if ($output_warning ne "") {
$output .= $output_append . "WARNING - $WAlertCount health issue(s) found: $output_warning";
}
if ($status == 0) {
$output = "All $OKCount health checks are green";
}
$self->{obj_esxd}->print_response(centreon::esxd::common::get_status($status) . "|$output\n");
}
1;

View File

@ -14,10 +14,6 @@ use centreon::plugins::perfdata;
my $manager_display = {};
my %ERRORS = ( "OK" => 0, "WARNING" => 1, "CRITICAL" => 2, "UNKNOWN" => 3, "PENDING" => 4);
my %MYERRORS = (0 => "OK", 1 => "WARNING", 3 => "CRITICAL", 7 => "UNKNOWN");
my %MYERRORS_MASK = ("CRITICAL" => 3, "WARNING" => 1, "UNKNOWN" => 7, "OK" => 0);
sub init_response {
$manager_display->{options} = centreon::plugins::options->new();
$manager_display->{output} = centreon::plugins::output->new(options => $manager_display->{options});
@ -30,64 +26,37 @@ sub response {
my (%options) = @_;
my $stdout;
{
if (!defined($options{stdout})) {
local *STDOUT;
$manager_display->{output}->{option_results}->{output_json} = 1;
open STDOUT, '>', \$stdout;
$manager_display->{output}->display(force_long_output => 1);
$manager_display->{output}->display(force_long_output => 1, nolabel => 1);
} else {
$stdout = $options{stdout};
}
print "====stdout === $stdout===\n";
zmq_sendmsg($options{endpoint}, $options{identity}, ZMQ_SNDMORE);
zmq_sendmsg($options{endpoint}, "RESPSERVER " . $stdout);
}
sub errors_mask {
my ($status, $state) = @_;
$status |= $MYERRORS_MASK{$state};
return $status;
}
sub get_status {
my ($state) = @_;
return $ERRORS{$MYERRORS{$state}};
}
sub response_client2 {
my ($obj_esxd, $id, $msg) = @_;
# Avoid croak kill. Can be happened (not often)
eval {
${$obj_esxd->{sockets}->{$id}->{obj}}->send($msg);
};
$obj_esxd->{read_select}->remove(${$obj_esxd->{sockets}->{$id}->{obj}});
close ${$obj_esxd->{sockets}->{$id}->{obj}};
delete $obj_esxd->{sockets}->{$id};
}
sub response_client1 {
my ($obj_esxd, $rh, $current_fileno, $msg) = @_;
# Avoid croak kill. Can be happened (not often)
eval {
$rh->send($msg);
};
$obj_esxd->{read_select}->remove($rh);
close $rh;
delete $obj_esxd->{sockets}->{$current_fileno};
if (defined($options{reinit})) {
my $context = zmq_init();
$options{endpoint} = zmq_socket($context, ZMQ_DEALER);
zmq_connect($options{endpoint}, $options{reinit});
}
if (defined($options{identity})) {
zmq_sendmsg($options{endpoint}, $options{identity}, ZMQ_SNDMORE);
}
zmq_sendmsg($options{endpoint}, $options{token} . " " . $stdout);
}
sub vmware_error {
my ($obj_esxd, $lerror) = @_;
$manager_display->{output}->output_add(long_msg => $lerror);
$obj_esxd->{logger}->writeLogError("'" . $obj_esxd->{whoaim} . "' $lerror");
$lerror =~ s/\n/ /g;
if ($lerror =~ /NoPermissionFault/i) {
$obj_esxd->print_response("-2|Error: Not enough permissions\n");
$manager_display->{output}->output_add(severity => 'UNKNOWN',
short_msg => 'VMWare error: not enought permissions');
} else {
$obj_esxd->print_response("-1|Error: " . $lerror . "\n");
$manager_display->{output}->output_add(severity => 'UNKNOWN',
short_msg => 'VMWare error (verbose mode for more details)');
}
return undef;
}
@ -104,7 +73,7 @@ sub connect_vsphere {
password => $password);
alarm(0);
};
if($@) {
if ($@) {
$logger->writeLogError("'$whoaim' No response from VirtualCenter server") if($@ =~ /TIMEOUT/);
$logger->writeLogError("'$whoaim' You need to upgrade HTTP::Message!") if($@ =~ /HTTP::Message/);
$logger->writeLogError("'$whoaim' Login to VirtualCenter server failed: $@");
@ -120,12 +89,6 @@ sub connect_vsphere {
return 0;
}
sub output_add($$$$) {
my ($output_str, $output_append, $delim, $str) = (shift, shift, shift, shift);
$$output_str .= $$output_append . $str;
$$output_append = $delim;
}
sub simplify_number {
my ($number, $cnt) = @_;
$cnt = 2 if (!defined($cnt));
@ -252,7 +215,8 @@ sub generic_performance_values_historic {
my $perfdata = $obj_esxd->{perfmanager_view}->QueryPerf(querySpec => \@perf_query_spec);
if (!$$perfdata[0] || !defined($$perfdata[0]->value)) {
$obj_esxd->print_response("-3|Error: Cannot get value for counters. Maybe you have call a wrong instance.\n");
$manager_display->{output}->output_add(severity => 'UNKNOWN',
short_msg => 'Cannot get value for counters. Maybe you have call a wrong instance');
return undef;
}
foreach my $val (@$perfdata) {
@ -261,7 +225,8 @@ sub generic_performance_values_historic {
$results{$_->id->counterId . ":" . (defined($_->id->instance) ? $_->id->instance : "")} = undef;
next;
} elsif (!defined($_->value)) {
$obj_esxd->print_response("-3|Error: Cannot get value for counters. Maybe there is time sync problem (check the esxd server and the target also).\n");
$manager_display->{output}->output_add(severity => 'UNKNOWN',
short_msg => 'Cannot get value for counters. Maybe there is time sync problem (check the esxd server and the target also)');
return undef;
}
@ -330,8 +295,8 @@ sub get_entities_host {
}
if (!@$entity_views) {
my $status = 0;
$status = errors_mask($status, 'UNKNOWN');
$obj_esxd->print_response(get_status($status) . "|Object $view_type does not exist.\n");
$manager_display->{output}->output_add(severity => 'UNKNOWN',
short_msg => "Object $view_type does not exist");
return undef;
}
#eval {
@ -400,15 +365,15 @@ sub vm_state {
if ($connection_state !~ /^connected$/i) {
my $output = "VM '" . $vm . "' not connected. Current Connection State: '$connection_state'.";
my $status = errors_mask(0, $obj_esxd->{centreonesxd_config}->{vm_state_error});
$obj_esxd->print_response(get_status($status) . "|$output\n");
$manager_display->{output}->output_add(severity => $obj_esxd->{centreonesxd_config}->{vm_state_error},
short_msg => $output);
return 0;
}
if (!defined($nocheck_ps) && $power_state !~ /^poweredOn$/i) {
if (!defined($nocheck_ps) && $power_state !~ /^poweredOn$/i) {
my $output = "VM '" . $vm . "' not running. Current Power State: '$power_state'.";
my $status = errors_mask(0, $obj_esxd->{centreonesxd_config}->{vm_state_error});
$obj_esxd->print_response(get_status($status) . "|$output\n");
$manager_display->{output}->output_add(severity => $obj_esxd->{centreonesxd_config}->{vm_state_error},
short_msg => $output);
return 0;
}
@ -420,8 +385,8 @@ sub host_state {
if ($connection_state !~ /^connected$/i) {
my $output = "Host '" . $host . "' not connected. Current Connection State: '$connection_state'.";
my $status = errors_mask(0, $obj_esxd->{centreonesxd_config}->{host_state_error});
$obj_esxd->print_response(get_status($status) . "|$output\n");
$manager_display->{output}->output_add(severity => $obj_esxd->{centreonesxd_config}->{host_state_error},
short_msg => $output);
return 0;
}
@ -443,7 +408,7 @@ sub stats_info {
} elsif ($$args[0] ne '' and $num_connection >= $$args[0]) {
$status = errors_mask($status, 'WARNING');
}
response_client1($obj_esxd, $rh, $current_fileno, get_status($status) . "|$output\n");
#response_client1($obj_esxd, $rh, $current_fileno, get_status($status) . "|$output\n");
}
1;

View File

@ -0,0 +1,299 @@
#!/usr/bin/perl -w
package centreon::esxd::connector;
use strict;
use VMware::VIRuntime;
use VMware::VILib;
use JSON;
use ZMQ::LibZMQ3;
use ZMQ::Constants qw(:all);
use File::Basename;
use POSIX ":sys_wait_h";
use centreon::script;
use centreon::esxd::common;
my %handlers = (TERM => {}, HUP => {}, CHLD => {});
my ($connector, $backend);
sub new {
my ($class, %options) = @_;
$connector = {};
bless $connector, $class;
$connector->{child_proc} = {};
$connector->{return_child} = {};
$connector->{vsphere_connected} = 0;
$connector->{last_time_vsphere} = undef;
$connector->{keeper_session_time} = undef;
$connector->{last_time_check} = undef;
$connector->{perfmanager_view} = undef;
$connector->{perfcounter_cache} = {};
$connector->{perfcounter_cache_reverse} = {};
$connector->{perfcounter_refreshrate} = 20;
$connector->{perfcounter_speriod} = -1;
$connector->{stop} = 0;
$connector->{childs_vpshere_pid} = {};
$connector->{session1} = undef;
$connector->{modules_registry} = $options{modules_registry};
$connector->{logger} = $options{logger};
$connector->{whoaim} = $options{name};
$connector->{module_date_parse_loaded} = $options{module_date_parse_loaded};
$connector->{config_child_timeout} = $options{config}->{timeout};
$connector->{config_stop_child_timeout} = $options{config}->{timeout_kill};
$connector->{config_vsphere_session_heartbeat} = $options{config}->{refresh_keeper_session};
$connector->{config_vsphere_connect_timeout} = $options{config}->{timeout_vsphere};
$connector->{config_vsphere_url} = $options{config}->{vsphere_server}->{$options{name}}->{url};
$connector->{config_vsphere_user} = $options{config}->{vsphere_server}->{$options{name}}->{username};
$connector->{config_vsphere_pass} = $options{config}->{vsphere_server}->{$options{name}}->{password};
return $connector;
}
sub set_signal_handlers {
my $self = shift;
$SIG{TERM} = \&class_handle_TERM;
$handlers{TERM}->{$self} = sub { $self->handle_TERM() };
$SIG{HUP} = \&class_handle_HUP;
$handlers{HUP}->{$self} = sub { $self->handle_HUP() };
$SIG{CHLD} = \&class_handle_CHLD;
$handlers{CHLD}->{$self} = sub { $self->handle_CHLD() };
}
sub class_handle_TERM {
foreach (keys %{$handlers{TERM}}) {
&{$handlers{TERM}->{$_}}();
}
}
sub class_handle_HUP {
foreach (keys %{$handlers{HUP}}) {
&{$handlers{HUP}->{$_}}();
}
}
sub class_handle_CHLD {
foreach (keys %{$handlers{CHLD}}) {
&{$handlers{CHLD}->{$_}}();
}
}
sub handle_TERM {
my $self = shift;
$self->{logger}->writeLogInfo("$$ Receiving order to stop...");
$self->{stop} = 1;
}
sub handle_HUP {
my $self = shift;
$self->{logger}->writeLogInfo("$$ Receiving order to reload...");
# TODO
}
sub handle_CHLD {
my $self = shift;
my $child_pid;
while (($child_pid = waitpid(-1, &WNOHANG)) > 0) {
$self->{return_child}{$child_pid} = {status => 1, rtime => time()};
}
$SIG{CHLD} = \&class_handle_CHLD;
}
sub response_router {
my ($self, %options) = @_;
my $manager = centreon::esxd::common::init_response();
$manager->{output}->output_add(severity => $options{severity},
short_msg => $options{msg});
$manager->{output}->{plugin} = $options{identity};
centreon::esxd::common::response(token => 'RESPSERVER2', endpoint => $backend);
}
sub verify_child {
my $self = shift;
my $progress = 0;
# Verify process
foreach (keys %{$self->{child_proc}}) {
# Check ctime
if (time() - $self->{child_proc}->{$_}->{ctime} > $self->{config_child_timeout}) {
$self->response_router(severity => 'UNKNOWN', msg => 'Timeout process',
identity => $_);
kill('INT', $self->{child_proc}->{$_}->{pid});
delete $self->{child_proc}->{$_};
} else {
$progress++;
}
}
# Clean old hash CHILD (security)
foreach (keys %{$self->{return_child}}) {
if (time() - $self->{return_child}->{$_}->{rtime} > 600) {
$self->{logger}->writeLogInfo("Clean Old return_child list = " . $_);
delete $self->{return_child}->{$_};
}
}
return $progress;
}
sub reqclient {
my ($self, %options) = @_;
my $result;
eval {
$result = JSON->new->utf8->decode($options{data});
};
if ($@) {
$self->{logger}->writeLogError("Cannot decode JSON: $@ (options{data}");
return ;
}
if ($self->{vsphere_connected}) {
$self->{logger}->writeLogInfo("vpshere '" . $self->{whoaim} . "' handler asking: $options{data}");
$self->{child_proc}->{$result->{identity}} = { ctime => time() };
$self->{child_proc}->{$result->{identity}}->{pid} = fork;
if (!$self->{child_proc}->{$result->{identity}}->{pid}) {
$self->{modules_registry}->{$result->{command}}->set_connector(connector => $self);
$self->{modules_registry}->{$result->{command}}->initArgs(arguments => $result);
$self->{modules_registry}->{$result->{command}}->run();
centreon::esxd::common::response(token => 'RESPSERVER2', endpoint => $backend, reinit => 'ipc://routing.ipc');
exit(0);
}
} else {
$self->response_router(severity => 'UNKNOWN', msg => 'Container connection problem',
identity => $result->{identity});
}
}
sub vsphere_event {
while (1) {
# Process all parts of the message
my $message = zmq_recvmsg($backend);
my $data = zmq_msg_data($message);
if ($data =~ /^REQCLIENT\s+(.*)$/msi) {
$connector->reqclient(data => $1);
}
my $more = zmq_getsockopt($backend, ZMQ_RCVMORE);
last unless $more;
}
}
sub run {
my ($connector) = shift;
my $timeout_process = 0;
my $context = zmq_init();
$backend = zmq_socket($context, ZMQ_DEALER);
zmq_setsockopt($backend, ZMQ_IDENTITY, "server-" . $connector->{whoaim});
zmq_connect($backend, 'ipc://routing.ipc');
# Initialize poll set
my @poll = (
{
socket => $backend,
events => ZMQ_POLLIN,
callback => \&vsphere_event,
},
);
while (1) {
my $progress = $connector->verify_child();
#####
# Manage ending
#####
if ($connector->{stop} && $timeout_process > $connector->{config_stop_child_timeout}) {
$connector->{logger}->writeLogError("'" . $connector->{whoaim} . "' Kill child not gently.");
foreach (keys %{$connector->{child_proc}}) {
kill('INT', $connector->{child_proc}->{$_}->{pid});
}
$progress = 0;
}
if ($connector->{stop} && !$progress) {
if ($connector->{vsphere_connected}) {
eval {
$connector->{session1}->logout();
};
}
exit (0);
}
###
# Manage vpshere connection
###
if (defined($connector->{last_time_vsphere}) && defined($connector->{last_time_check})
&& $connector->{last_time_vsphere} < $connector->{last_time_check}) {
$connector->{logger}->writeLogError("'" . $connector->{whoaim} . "' Disconnect");
$connector->{vsphere_connected} = 0;
eval {
$connector->{session1}->logout();
};
}
if ($connector->{vsphere_connected} == 0) {
if (!centreon::esxd::common::connect_vsphere($connector->{logger},
$connector->{whoaim},
$connector->{config_vsphere_connect_timeout},
\$connector->{session1},
$connector->{config_vsphere_url},
$connector->{config_vsphere_user},
$connector->{config_vsphere_pass})) {
$connector->{logger}->writeLogInfo("'" . $connector->{whoaim} . "' Vsphere connection ok");
$connector->{logger}->writeLogInfo("'" . $connector->{whoaim} . "' Create perf counters cache in progress");
if (!centreon::esxd::common::cache_perf_counters($connector)) {
$connector->{last_time_vsphere} = time();
$connector->{keeper_session_time} = time();
$connector->{vsphere_connected} = 1;
$connector->{logger}->writeLogInfo("'" . $connector->{whoaim} . "' Create perf counters cache done");
}
}
}
###
# Manage session time
###
if (defined($connector->{keeper_session_time}) &&
(time() - $connector->{keeper_session_time}) > ($connector->{config_vsphere_session_heartbeat} * 60)) {
my $stime;
eval {
$stime = $connector->{session1}->get_service_instance()->CurrentTime();
$connector->{keeper_session_time} = time();
};
if ($@) {
$connector->{logger}->writeLogError("$@");
$connector->{logger}->writeLogError("'" . $connector->{whoaim} . "' Ask a new connection");
# Ask a new connection
$connector->{last_time_check} = time();
} else {
$connector->{logger}->writeLogInfo("'" . $connector->{whoaim} . "' Get current time = " . Data::Dumper::Dumper($stime));
}
}
my $data_element;
my @rh_set;
if ($connector->{vsphere_connected} == 0) {
sleep(5);
}
if ($connector->{stop} != 0) {
sleep(1);
$timeout_process++;
next;
}
zmq_poll(\@poll, 5000);
}
}
1;
__END__

View File

@ -1,19 +1,22 @@
#!/usr/bin/perl -w
#!/usr/bin/perl
package centreon::script::centreonesxd;
use strict;
use warnings;
use VMware::VIRuntime;
use VMware::VILib;
use ZMQ::LibZMQ3;
use ZMQ::Constants qw(:all);
use File::Basename;
use POSIX ":sys_wait_h";
use JSON;
use Data::Dumper;
use centreon::script;
use centreon::esxd::common;
use centreon::esxd::connector;
my ($centreonesxd, $frontend, $backend);
my ($centreonesxd, $frontend);
BEGIN {
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
@ -22,8 +25,9 @@ BEGIN {
use base qw(centreon::script);
use vars qw(%centreonesxd_config);
my $VERSION = "1.5.6";
my $VERSION = "1.6.0";
my %handlers = (TERM => {}, HUP => {}, CHLD => {});
my @load_modules = ('centreon::esxd::cmdcountvmhost',
'centreon::esxd::cmdcpuhost',
'centreon::esxd::cmdcpuvm',
@ -87,21 +91,9 @@ sub new {
}
);
$self->{child_proc} = {};
$self->{return_child} = {};
$self->{vsphere_connected} = 0;
$self->{last_time_vsphere} = undef;
$self->{keeper_session_time} = undef;
$self->{last_time_check} = undef;
$self->{perfmanager_view} = undef;
$self->{perfcounter_cache} = {};
$self->{perfcounter_cache_reverse} = {};
$self->{perfcounter_refreshrate} = 20;
$self->{perfcounter_speriod} = -1;
$self->{stop} = 0;
$self->{counter_request_id} = 0;
$self->{childs_vpshere_pid} = {};
$self->{session1} = undef;
$self->{counter} = 0;
$self->{whoaim} = undef; # to know which vsphere to connect
$self->{module_date_parse_loaded} = 0;
@ -219,19 +211,13 @@ sub handle_CHLD {
$SIG{CHLD} = \&class_handle_CHLD;
}
sub print_response {
my $self = shift;
print $self->{global_id} . "|" . $_[0];
}
sub load_module {
my $self = shift;
for (@_) {
(my $file = "$_.pm") =~ s{::}{/}g;
require $file;
my $obj = $_->new($self->{logger}, $self);
my $obj = $_->new($self->{logger});
$self->{modules_registry}->{$obj->getCommandName()} = $obj;
}
}
@ -263,35 +249,64 @@ sub verify_child_vsphere {
$count++;
}
}
return $count;
}
sub verify_child {
my $self = shift;
my $progress = 0;
# Verify process
foreach (keys %{$self->{child_proc}}) {
# Check ctime
if (time() - $self->{child_proc}->{$_}->{ctime} > $self->{centreonesxd_config}->{timeout}) {
print "===timeout papa===\n";
#print $handle_writer_pipe "$_|-1|Timeout Process.\n";
kill('INT', $self->{child_proc}->{$_}->{pid});
delete $self->{child_proc}->{$_};
} else {
$progress++;
}
sub request {
my ($self, %options) = @_;
# Decode json
my $result;
eval {
$result = JSON->new->utf8->decode($options{data});
};
if ($@) {
$options{manager}->{output}->output_add(severity => 'UNKNOWN',
short_msg => "Cannot decode json result: $@");
centreon::esxd::common::response(token => 'RESPSERVER', endpoint => $frontend, identity => $options{identity});
return ;
}
# Clean old hash CHILD (security)
foreach (keys %{$self->{return_child}}) {
if (time() - $self->{return_child}->{$_}->{rtime} > 600) {
$self->{logger}->writeLogInfo("Clean Old return_child list = " . $_);
delete $self->{return_child}->{$_};
}
if (!defined($self->{modules_registry}->{$result->{command}})) {
$options{manager}->{output}->output_add(severity => 'UNKNOWN',
short_msg => "Unknown method name '$result->{command}'");
centreon::esxd::common::response(token => 'RESPSERVER', endpoint => $frontend, identity => $options{identity});
return ;
}
if ($self->{modules_registry}->{$result->{command}}->checkArgs(manager => $options{manager},
arguments => $result)) {
centreon::esxd::common::response(token => 'RESPSERVER', endpoint => $frontend, identity => $options{identity});
return ;
}
if (!defined($self->{centreonesxd_config}->{vsphere_server}->{$result->{container}})) {
$options{manager}->{output}->output_add(severity => 'UNKNOWN',
short_msg => "Unknown container name '$result->{container}'");
centreon::esxd::common::response(token => 'RESPSERVER', endpoint => $frontend, identity => $options{identity});
return ;
}
return $progress;
zmq_sendmsg($frontend, "server-" . $result->{container}, ZMQ_SNDMORE);
zmq_sendmsg($frontend, 'REQCLIENT ' . $options{data});
}
sub repserver {
my ($self, %options) = @_;
# Decode json
my $result;
eval {
$result = JSON->new->utf8->decode($options{data});
};
if ($@) {
$self->{logger}->writeLogError("Cannot decode JSON: $@ (options{data}");
return ;
}
$result->{plugin}->{name} =~ /^client-(.*)$/;
my $identity = 'client-' . pack('H*', $1);
centreon::esxd::common::response(token => 'RESPSERVER', endpoint => $frontend,
identity => $identity, stdout => $options{data});
}
sub router_event {
@ -304,183 +319,37 @@ sub router_event {
my $data = zmq_msg_data($message);
my $manager = centreon::esxd::common::init_response();
if ($centreonesxd->{stop} != 0) {
# We quit so we say we're leaving ;)
$manager->{output}->output_add(severity => 'UNKNOWN',
short_msg => 'Daemon is restarting...');
centreon::esxd::common::response(endpoint => $frontend, identity => $identity);
} elsif ($data =~ /^REQCLIENT\s+(.*)$/) {
zmq_sendmsg($frontend, "server-" . $1, ZMQ_SNDMORE);
zmq_sendmsg($frontend, $data);
my $manager = centreon::esxd::common::init_response();
$manager->{output}->output_add(severity => 'OK',
short_msg => 'ma reponse enfin');
centreon::esxd::common::response(endpoint => $frontend, identity => $identity);
centreon::esxd::common::response(token => 'RESPSERVER', endpoint => $frontend, identity => $identity);
} elsif ($data =~ /^REQCLIENT\s+(.*)$/msi) {
$centreonesxd->request(identity => $identity, data => $1, manager => $manager);
} elsif ($data =~ /^RESPSERVER2\s+(.*)$/msi) {
$centreonesxd->repserver(data => $1, manager => $manager);
}
my $more = zmq_getsockopt($frontend, ZMQ_RCVMORE);
last unless $more;
}
}
sub vsphere_event {
while (1) {
# Process all parts of the message
my $message = zmq_recvmsg($backend);
print "=== " . Data::Dumper::Dumper(zmq_msg_data($message)) . " ===\n";
zmq_sendmsg($backend, 'bien tutu');
print "=PLAPLA=\n";
my $data = zmq_msg_data($message);
if (defined($message)) {
if ($centreonesxd->{vsphere_connected}) {
$centreonesxd->{logger}->writeLogInfo("vpshere '" . $centreonesxd->{whoaim} . "' handler asking: $message");
$centreonesxd->{child_proc}->{pid} = fork;
if (!$centreonesxd->{child_proc}->{pid}) {
# Child
$centreonesxd->{logger}->{log_mode} = 1 if ($centreonesxd->{logger}->{log_mode} == 0);
my ($id, $name, @args) = split /\Q$centreonesxd->{separatorin}\E/, $message;
$centreonesxd->{global_id} = $id;
$centreonesxd->{modules_registry}->{$name}->initArgs(@args);
$centreonesxd->{modules_registry}->{$name}->run();
exit(0);
}
} else {
#print $handle_writer_pipe "$id|-1|Vsphere connection error.\n";
}
}
my $more = zmq_getsockopt($backend, ZMQ_RCVMORE);
#zmq_sendmsg($backend, $message, $more ? ZMQ_SNDMORE : 0);
last unless $more;
}
}
sub vsphere_handler {
$centreonesxd = shift;
my $timeout_process;
my $context = zmq_init();
$backend = zmq_socket($context, ZMQ_DEALER);
zmq_setsockopt($backend, ZMQ_IDENTITY, "server-" . $centreonesxd->{whoaim});
zmq_connect($backend, 'ipc://routing.ipc');
#zmq_sendmsg($backend, 'ready');
# Initialize poll set
my @poll = (
{
socket => $backend,
events => ZMQ_POLLIN,
callback => \&vsphere_event,
},
);
while (1) {
my $progress = $centreonesxd->verify_child();
#####
# Manage ending
#####
if ($centreonesxd->{stop} && $timeout_process > $centreonesxd->{centreonesxd_config}->{timeout_kill}) {
$centreonesxd->{logger}->writeLogError("'" . $centreonesxd->{whoaim} . "' Kill child not gently.");
foreach (keys %{$centreonesxd->{child_proc}}) {
kill('INT', $centreonesxd->{child_proc}->{$_}->{pid});
}
$progress = 0;
}
if ($centreonesxd->{stop} && !$progress) {
if ($centreonesxd->{vsphere_connected}) {
eval {
$centreonesxd->{session1}->logout();
};
}
exit (0);
}
###
# Manage vpshere connection
###
if (defined($centreonesxd->{last_time_vsphere}) && defined($centreonesxd->{last_time_check})
&& $centreonesxd->{last_time_vsphere} < $centreonesxd->{last_time_check}) {
$centreonesxd->{logger}->writeLogError("'" . $centreonesxd->{whoaim} . "' Disconnect");
$centreonesxd->{vsphere_connected} = 0;
eval {
$centreonesxd->{session1}->logout();
};
}
if ($centreonesxd->{vsphere_connected} == 0) {
if (!centreon::esxd::common::connect_vsphere($centreonesxd->{logger},
$centreonesxd->{whoaim},
$centreonesxd->{centreonesxd_config}->{timeout_vsphere},
\$centreonesxd->{session1},
$centreonesxd->{centreonesxd_config}->{vsphere_server}->{$centreonesxd->{whoaim}}->{url},
$centreonesxd->{centreonesxd_config}->{vsphere_server}->{$centreonesxd->{whoaim}}->{username},
$centreonesxd->{centreonesxd_config}->{vsphere_server}->{$centreonesxd->{whoaim}}->{password})) {
$centreonesxd->{logger}->writeLogInfo("'" . $centreonesxd->{whoaim} . "' Vsphere connection ok");
$centreonesxd->{logger}->writeLogInfo("'" . $centreonesxd->{whoaim} . "' Create perf counters cache in progress");
if (!centreon::esxd::common::cache_perf_counters($centreonesxd)) {
$centreonesxd->{last_time_vsphere} = time();
$centreonesxd->{keeper_session_time} = time();
$centreonesxd->{vsphere_connected} = 1;
$centreonesxd->{logger}->writeLogInfo("'" . $centreonesxd->{whoaim} . "' Create perf counters cache done");
}
}
}
###
# Manage session time
###
if (defined($centreonesxd->{keeper_session_time}) &&
(time() - $centreonesxd->{keeper_session_time}) > ($centreonesxd->{centreonesxd_config}->{refresh_keeper_session} * 60)) {
my $stime;
eval {
$stime = $centreonesxd->{session1}->get_service_instance()->CurrentTime();
$centreonesxd->{keeper_session_time} = time();
};
if ($@) {
$centreonesxd->{logger}->writeLogError("$@");
$centreonesxd->{logger}->writeLogError("'" . $centreonesxd->{whoaim} . "' Ask a new connection");
# Ask a new connection
$centreonesxd->{last_time_check} = time();
} else {
$centreonesxd->{logger}->writeLogInfo("'" . $centreonesxd->{whoaim} . "' Get current time = " . Data::Dumper::Dumper($stime));
}
}
my $data_element;
my @rh_set;
if ($centreonesxd->{vsphere_connected} == 0) {
sleep(5);
}
if ($centreonesxd->{stop} != 0) {
sleep(1);
next;
}
print "====chaton===\n";
zmq_poll(\@poll, 5000);
}
}
sub create_vsphere_child {
my ($self, %options) = @_;
$self->{whoaim} = $options{vsphere_name};
$self->{centreonesxd_config}->{vsphere_server}->{$self->{whoaim}}->{running} = 0;
$self->{logger}->writeLogInfo("Create vsphere sub-process for '" . $options{vsphere_name} . "'");
$self->{whoaim} = $options{vsphere_name};
my $child_vpshere_pid = fork();
if ($child_vpshere_pid == 0) {
$self->vsphere_handler();
my $connector = centreon::esxd::connector->new(name => $self->{whoaim},
modules_registry => $self->{modules_registry},
module_date_parse_loaded => $self->{module_date_parse_loaded},
config => $self->{centreonesxd_config},
logger => $self->{logger});
$connector->run();
exit(0);
}
$self->{childs_vpshere_pid}->{$child_vpshere_pid} = $self->{whoaim};