enh(vmware-connector): add the ability to load configuration from a json file (#5192)

Co-authored-by: sdepassio <114986849+sdepassio@users.noreply.github.com>
Co-authored-by: Evan-Adam <152897682+Evan-Adam@users.noreply.github.com>
REFS: CTOR-786
This commit is contained in:
omercier 2024-10-03 14:50:14 +02:00 committed by GitHub
parent b9d19ede94
commit df03cc5037
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
63 changed files with 866 additions and 196 deletions

View File

@ -39,6 +39,11 @@ contents:
dst: "/usr/share/perl5/centreon/script/centreon_vmware.pm"
packager: deb
- src: "../src/centreon/script/centreon_vmware_convert_config_file"
dst: "/usr/bin/centreon_vmware_convert_config_file"
file_info:
mode: 0755
- src: "../src/centreon_vmware.pl"
dst: "/usr/bin/centreon_vmware.pl"
file_info:
@ -76,23 +81,25 @@ scripts:
overrides:
rpm:
depends:
- perl-VMware-vSphere >= 5.1
- perl(ZMQ::LibZMQ4)
- perl(ZMQ::Constants)
- perl(LWP::Protocol::https)
- perl(Crypt::OpenSSL::AES)
- perl(IO::Socket::INET6)
- perl(JSON::XS)
- perl(LWP::Protocol::https)
- perl(ZMQ::Constants)
- perl(ZMQ::LibZMQ4)
- perl-Net-Curl
- perl-VMware-vSphere >= 5.1
deb:
depends:
- perl-vmware-vsphere
- libzmq-libzmq4-perl
- libzmq-constants-perl
- liblwp-protocol-https-perl
- libcrypt-openssl-aes-perl
- libio-socket-inet6-perl
- libjson-xs-perl
- liblwp-protocol-https-perl
- libnet-curl-perl
- libtext-template-perl
- libzmq-constants-perl
- libzmq-libzmq4-perl
- perl-vmware-vsphere
rpm:
signature:

View File

@ -0,0 +1,28 @@
{
"bind": "*",
"case_insensitive": 0,
"credstore_file": "/root/.vmware/credstore/vicredentials.xml",
"credstore_use": 0,
"dynamic_timeout_kill": 86400,
"ipc_file": "/tmp/centreon_vmware/routing.ipc",
"port": 5700,
"refresh_keeper_session": 15,
"timeout": 60,
"timeout_kill": 30,
"timeout_vsphere": 60,
"vsan_sdk_path": "/usr/local/share/perl5/VMware",
"vsphere_server": [
{
"name": "additional",
"password": "XXXXXX",
"url": "https://vcenter2/sdk",
"username": "XXXXXX"
},
{
"name": "default",
"password": "XXXXXX",
"url": "https://vcenter/sdk",
"username": "XXXXXX"
}
]
}

View File

@ -1,10 +1,28 @@
%centreon_vmware_config = (
vsphere_server => {
'default' => {'url' => 'https://vcenter/sdk',
'username' => 'XXXXXX',
'password' => 'XXXXXX'}
}
vsphere_server => {
'default' => {
'url' => 'https://vcenter/sdk',
'username' => 'XXXXXX',
'password' => 'XXXXXX'
},
'additional' => {
'url' => 'https://vcenter2/sdk',
'username' => 'XXXXXX',
'password' => 'XXXXXX'
}
},
credstore_use => 0,
credstore_file => '/root/.vmware/credstore/vicredentials.xml',
timeout_vsphere => 60,
timeout => 60,
timeout_kill => 30,
dynamic_timeout_kill => 86400,
refresh_keeper_session => 15,
bind => '*',
port => 5700,
ipc_file => '/tmp/centreon_vmware/routing.ipc',
case_insensitive => 0,
vsan_sdk_path => '/usr/local/share/perl5/VMware'
);
1;

View File

@ -1,4 +1,4 @@
## Copyright 2016 Centreon
# Copyright 2024 Centreon
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
## Copyright 2016 Centreon
# Copyright 2024 Centreon
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.

View File

@ -1,15 +1,15 @@
#!/usr/bin/perl
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
@ -32,6 +32,7 @@ use JSON::XS;
use centreon::vmware::script;
use centreon::vmware::common;
use centreon::vmware::connector;
use centreon::script::centreonvault;
my ($centreon_vmware, $frontend);
@ -52,7 +53,6 @@ BEGIN {
}
use base qw(centreon::vmware::script);
use vars qw(%centreon_vmware_config);
my $VERSION = '3.2.6';
my %handlers = (TERM => {}, HUP => {}, CHLD => {});
@ -108,43 +108,90 @@ sub new {
bless $self, $class;
$self->add_options(
'config-extra=s' => \$self->{opt_extra}
'config-extra=s' => \$self->{opt_extra},
'check-config' => \$self->{opt_check_config},
'vault-config=s' => \$self->{opt_vault_config}
);
%{$self->{centreon_vmware_default_config}} =
(
credstore_use => 0,
credstore_file => '/root/.vmware/credstore/vicredentials.xml',
timeout_vsphere => 60,
timeout => 60,
timeout_kill => 30,
dynamic_timeout_kill => 86400,
refresh_keeper_session => 15,
bind => '*',
port => 5700,
ipc_file => '/tmp/centreon_vmware/routing.ipc',
case_insensitive => 0,
vsphere_server => {
#'default' => {'url' => 'https://XXXXXX/sdk',
# 'username' => 'XXXXX',
# 'password' => 'XXXXX'},
#'testvc' => {'url' => 'https://XXXXXX/sdk',
# 'username' => 'XXXXX',
# 'password' => 'XXXXXX'}
},
vsan_sdk_path => '/usr/local/share/perl5/VMware'
);
%{$self->{centreon_vmware_default_config}} = (
credstore_use => 0,
credstore_file => '/root/.vmware/credstore/vicredentials.xml',
timeout_vsphere => 60,
timeout => 60,
timeout_kill => 30,
dynamic_timeout_kill => 86400,
refresh_keeper_session => 15,
bind => '*',
port => 5700,
ipc_file => '/tmp/centreon_vmware/routing.ipc',
case_insensitive => 0,
vsphere_server => {
#'default' => {'url' => 'https://XXXXXX/sdk',
# 'username' => 'XXXXX',
# 'password' => 'XXXXX'},
#'testvc' => {'url' => 'https://XXXXXX/sdk',
# 'username' => 'XXXXX',
# 'password' => 'XXXXXX'}
},
vsan_sdk_path => '/usr/local/share/perl5/VMware'
);
$self->{return_child} = {};
$self->{stop} = 0;
$self->{childs_vpshere_pid} = {};
$self->{counter_stats} = {};
$self->{whoaim} = undef; # to know which vsphere to connect
$self->{modules_registry} = {};
$self->{return_child} = {};
$self->{stop} = 0;
$self->{children_vpshere_pid} = {};
$self->{counter_stats} = {};
$self->{whoaim} = undef; # to know which vsphere to connect
$self->{modules_registry} = {};
$self->{vault} = {};
return $self;
}
# read_configuration: reads the configuration file given as parameter
sub read_configuration {
my ($self, %options) = @_;
$self->{logger}->writeLogDebug("Reading configuration from " . $self->{opt_extra});
my $centreon_vmware_config_from_json;
if ($self->{opt_extra} =~ /.*\.pm$/i) {
our %centreon_vmware_config;
# loads the .pm configuration (compile time)
require($self->{opt_extra}) or $self->{logger}->writeLogFatal("There has been an error while requiring file " . $self->{opt_extra});
# Concatenation of the default parameters with the ones from the config file
$self->{centreon_vmware_config} = {%{$self->{centreon_vmware_default_config}}, %centreon_vmware_config};
} elsif ($self->{opt_extra} =~ /.*\.json$/i) {
$centreon_vmware_config_from_json = centreon::vmware::common::parse_json_file( 'json_file' => $self->{opt_extra} );
if (defined($centreon_vmware_config_from_json->{error_message})) {
$self->{logger}->writeLogFatal("Error while parsing " . $self->{opt_extra} . ": " . $centreon_vmware_config_from_json->{error_message});
}
# The structure of the JSON is different from the .pm file. The code was designed to work with the latter, so
# the structure of $self->{centreon_vmware_config} must be adapted after parsing to avoid a massive refactoring of
# the whole program. The wanted structure is a key-object dictionary instead of an array of objects.
my %vsphere_server_dict = map { lc($_->{name}) => $_ } @{$centreon_vmware_config_from_json->{vsphere_server}};
# Replace the "raw" structure from the JSON file.
$centreon_vmware_config_from_json->{vsphere_server} = \%vsphere_server_dict;
# Concatenation of the default parameters with the ones from the config file
$self->{centreon_vmware_config} = {%{$self->{centreon_vmware_default_config}}, %$centreon_vmware_config_from_json};
} else {
$self->{logger}->writeLogFatal($self->{opt_extra} . " does not seem to be in a supported format (supported: .pm or .json).");
}
}
# report_config_check: writes a report of what has been loaded from the configuration file
sub report_config_check {
my ($self, %options) = @_;
my $nb_server_entries = scalar(keys %{$self->{centreon_vmware_config}->{vsphere_server}});
my $entry_spelling = ($nb_server_entries > 1) ? 'entries' : 'entry';
my $report = "Configuration file " . $self->{opt_extra} . " has been read correctly and has "
. $nb_server_entries . " " . $entry_spelling . ".";
$self->{logger}->writeLogInfo($report);
return $report;
}
sub init {
my $self = shift;
$self->SUPER::init();
@ -152,22 +199,31 @@ sub init {
# redefine to avoid out when we try modules
$SIG{__DIE__} = undef;
if (!defined($self->{opt_extra})) {
if ( ! defined($self->{opt_extra}) ) {
$self->{opt_extra} = "/etc/centreon/centreon_vmware.pm";
}
if (-f $self->{opt_extra}) {
require $self->{opt_extra};
} else {
$self->{logger}->writeLogInfo("Can't find extra config file $self->{opt_extra}");
if ( ! -f $self->{opt_extra} ) {
$self->{logger}->writeLogFatal(
"Can't find config file '$self->{opt_extra}'. If a migration from "
. "/etc/centreon/centreon_vmware.pm to /etc/centreon/centreon_vmware.json is required, you may "
. "centreon_vmware_convert_config_file /etc/centreon/centreon_vmware.pm > /etc/centreon/centreon_vmware.json"
);
}
$self->{centreon_vmware_config} = {%{$self->{centreon_vmware_default_config}}, %centreon_vmware_config};
$self->read_configuration(filename => $self->{opt_extra});
foreach my $name (keys %{$self->{centreon_vmware_config}->{vsphere_server}}) {
my $iname = lc($name);
$self->{centreon_vmware_config}->{vsphere_server}->{$iname} = delete $self->{centreon_vmware_config}->{vsphere_server}->{$name};
if (! defined($self->{opt_vault_config}) || $self->{opt_vault_config} eq '') {
$self->{opt_vault_config} = '/var/lib/centreon/vault/vault.json';
$self->{logger}->writeLogInfo("No vault config file given. Applying default: " . $self->{opt_vault_config});
}
$self->{logger}->writeLogDebug("Vault config file " . $self->{opt_vault_config} . " exists. Creating the vault object.");
$self->{vault} = centreon::script::centreonvault->new(
'logger' => $self->{logger},
'config_file' => $self->{opt_vault_config}
);
##### Load modules
$self->load_module(@load_modules);
@ -194,23 +250,42 @@ sub init {
$self->{logger}->writeLogError("Credstore init failed: $@");
exit(1);
}
} else {
$self->{logger}->writeLogDebug("Not using credstore.");
$self->{centreon_vmware_config}->{credstore_use} = 0;
}
###
# Get password
###
foreach (keys %{$self->{centreon_vmware_config}->{vsphere_server}}) {
my $lpassword = VMware::VICredStore::get_password(server => $_, username => $self->{centreon_vmware_config}->{vsphere_server}->{$_}->{username});
if (!defined($lpassword)) {
$self->{logger}->writeLogError("Can't get password for couple host='" . $_ . "', username='" . $self->{centreon_vmware_config}->{vsphere_server}->{$_}->{username} . "' : $@");
exit(1);
# Get passwords
foreach my $server (keys %{$self->{centreon_vmware_config}->{vsphere_server}}) {
# If appropriate, get the password from the vmware credentials store
if ($self->{centreon_vmware_config}->{credstore_use} == 1) {
$self->{centreon_vmware_config}->{vsphere_server}->{$server}->{password} = VMware::VICredStore::get_password(
server => $server,
username => $self->{centreon_vmware_config}->{vsphere_server}->{$server}->{username}
);
if (!defined($self->{centreon_vmware_config}->{vsphere_server}->{$server}->{password})) {
$self->{logger}->writeLogFatal("Can't get password for couple host='" . $server . "', username='" . $self->{centreon_vmware_config}->{vsphere_server}->{$server}->{username} . "' : $@");
}
} else {
# we let the vault object handle the secrets
for my $key ('username', 'password') {
$self->{logger}->writeLogDebug("Retrieving secret: $key");
$self->{centreon_vmware_config}->{vsphere_server}->{$server}->{$key}
= $self->{vault}->get_secret($self->{centreon_vmware_config}->{vsphere_server}->{$server}->{$key});
}
$self->{centreon_vmware_config}->{vsphere_server}->{$_}->{password} = $lpassword;
}
}
my $config_check_report = $self->report_config_check();
if (defined($self->{opt_check_config})) {
print($config_check_report . " Exiting now.");
exit(0);
}
$self->set_signal_handlers;
}
sub set_signal_handlers {
my $self = shift;
@ -245,15 +320,15 @@ sub handle_TERM {
$self->{logger}->writeLogInfo("$$ Receiving order to stop...");
$self->{stop} = 1;
foreach (keys %{$self->{childs_vpshere_pid}}) {
foreach (keys %{$self->{children_vpshere_pid}}) {
kill('TERM', $_);
$self->{logger}->writeLogInfo("Send -TERM signal to '" . $self->{childs_vpshere_pid}->{$_} . "' process..");
$self->{logger}->writeLogInfo("Send -TERM signal to '" . $self->{children_vpshere_pid}->{$_} . "' process..");
}
}
sub handle_HUP {
my $self = shift;
$self->{logger}->writeLogInfo("$$ Receiving order to reload...");
$self->{logger}->writeLogInfo("$$ Receiving order to reload but it has not been implemented yet...");
# TODO
}
@ -276,7 +351,7 @@ sub load_module {
require $file;
my $obj = $_->new(logger => $self->{logger}, case_insensitive => $self->{centreon_vmware_config}->{case_insensitive});
$self->{modules_registry}->{ $obj->getCommandName() } = $obj;
}
}
}
sub verify_child_vsphere {
@ -286,24 +361,24 @@ sub verify_child_vsphere {
foreach (keys %{$self->{return_child}}) {
delete $self->{return_child}->{$_};
if (defined($self->{childs_vpshere_pid}->{$_})) {
if (defined($self->{children_vpshere_pid}->{$_})) {
if ($self->{stop} == 0) {
my $name = $self->{childs_vpshere_pid}->{$_};
$self->{logger}->writeLogError("Sub-process for '" . $self->{childs_vpshere_pid}->{$_} . "'???!! we relaunch it!!!");
my $name = $self->{children_vpshere_pid}->{$_};
$self->{logger}->writeLogError("Sub-process for '" . $self->{children_vpshere_pid}->{$_} . "'???!! we relaunch it!!!");
if ($self->{centreon_vmware_config}->{vsphere_server}->{$self->{childs_vpshere_pid}->{$_}}->{dynamic} == 0) {
if ($self->{centreon_vmware_config}->{vsphere_server}->{$self->{children_vpshere_pid}->{$_}}->{dynamic} == 0) {
# Can have the same pid (so we delete before)
delete $self->{childs_vpshere_pid}->{$_};
delete $self->{children_vpshere_pid}->{$_};
$self->create_vsphere_child(vsphere_name => $name, dynamic => 0);
} else {
$self->{logger}->writeLogError("Sub-process for '" . $self->{childs_vpshere_pid}->{$_} . "' is dead. But we don't relaunch it (dynamic sub-process)");
delete $self->{centreon_vmware_config}->{vsphere_server}->{$self->{childs_vpshere_pid}->{$_}};
delete $self->{childs_vpshere_pid}->{$_};
$self->{logger}->writeLogError("Sub-process for '" . $self->{children_vpshere_pid}->{$_} . "' is dead. But we don't relaunch it (dynamic sub-process)");
delete $self->{centreon_vmware_config}->{vsphere_server}->{$self->{children_vpshere_pid}->{$_}};
delete $self->{children_vpshere_pid}->{$_};
}
} else {
$self->{logger}->writeLogInfo("Sub-process for '" . $self->{childs_vpshere_pid}->{$_} . "' dead ???!!");
$self->{centreon_vmware_config}->{vsphere_server}->{$self->{childs_vpshere_pid}->{$_}}->{running} = 0;
delete $self->{childs_vpshere_pid}->{$_};
$self->{logger}->writeLogInfo("Sub-process for '" . $self->{children_vpshere_pid}->{$_} . "' dead ???!!");
$self->{centreon_vmware_config}->{vsphere_server}->{$self->{children_vpshere_pid}->{$_}}->{running} = 0;
delete $self->{children_vpshere_pid}->{$_};
}
}
}
@ -317,7 +392,7 @@ sub verify_child_vsphere {
time() - $self->{centreon_vmware_config}->{dynamic_timeout_kill} > $self->{centreon_vmware_config}->{vsphere_server}->{$_}->{last_request}) {
$self->{logger}->writeLogError("Send TERM signal for process '" . $_ . "': too many times without requests. We clean it.");
kill('TERM', $self->{centreon_vmware_config}->{vsphere_server}->{$_}->{pid});
}
}
}
return $count;
@ -329,11 +404,11 @@ sub waiting_ready {
return 1 if ($self->{centreon_vmware_config}->{vsphere_server}->{$options{container}}->{ready} == 1);
# Need to check if we need to relaunch (maybe it can have a problem)
$self->check_childs();
$self->check_children();
my $time = time();
# We wait 10 seconds
while ($self->{centreon_vmware_config}->{vsphere_server}->{$options{container}}->{ready} == 0 &&
while ($self->{centreon_vmware_config}->{vsphere_server}->{$options{container}}->{ready} == 0 &&
time() - $time < 10) {
zmq_poll($self->{poll}, 5000);
}
@ -368,7 +443,7 @@ sub request_dynamic {
};
$self->{logger}->writeLogError(
sprintf(
"Dynamic creation: identity = %s [address: %s] [username: %s] [password: %s]",
"Dynamic creation: identity = %s [address: %s] [username: %s] [password: %s]",
$container, $options{result}->{vsphere_address}, $options{result}->{vsphere_username}, $options{result}->{vsphere_password}
)
);
@ -436,7 +511,7 @@ sub request {
return if ($self->waiting_ready(
container => $result->{container}, manager => $options{manager},
identity => $options{identity}) == 0);
$self->{counter_stats}->{ $result->{container} }++;
my $flag = ZMQ_NOBLOCK | ZMQ_SNDMORE;
@ -465,7 +540,7 @@ sub repserver {
my $identity = 'client-' . pack('H*', $1);
centreon::vmware::common::response(
token => 'RESPSERVER', endpoint => $frontend,
token => 'RESPSERVER', endpoint => $frontend,
identity => $identity, force_response => $options{data}
);
}
@ -498,17 +573,18 @@ sub router_event {
}
centreon::vmware::common::free_response();
my $more = zmq_getsockopt($frontend, ZMQ_RCVMORE);
my $more = zmq_getsockopt($frontend, ZMQ_RCVMORE);
last unless $more;
}
}
sub check_childs {
sub check_children {
my ($self, %options) = @_;
my $count = $self->verify_child_vsphere();
$self->{logger}->writeLogDebug("$count child(ren) found. Stop ? : " . $self->{stop});
if ($self->{stop} == 1) {
# No childs
# No children
if ($count == 0) {
$self->{logger}->writeLogInfo("Quit main process");
zmq_close($frontend);
@ -516,7 +592,7 @@ sub check_childs {
}
}
}
sub create_vsphere_child {
my ($self, %options) = @_;
@ -527,7 +603,7 @@ sub create_vsphere_child {
my $child_vpshere_pid = fork();
if (!defined($child_vpshere_pid)) {
$self->{logger}->writeLogError("Cannot fork for '" . $options{vsphere_name} . "': $!");
$self->{logger}->writeLogError("Cannot fork for '" . $options{vsphere_name} . "': $!");
return -1;
}
if ($child_vpshere_pid == 0) {
@ -541,10 +617,11 @@ sub create_vsphere_child {
$connector->run();
exit(0);
}
$self->{childs_vpshere_pid}->{$child_vpshere_pid} = $self->{whoaim};
$self->{children_vpshere_pid}->{$child_vpshere_pid} = $self->{whoaim};
$self->{centreon_vmware_config}->{vsphere_server}->{$self->{whoaim}}->{running} = 1;
$self->{centreon_vmware_config}->{vsphere_server}->{$self->{whoaim}}->{dynamic} = $options{dynamic};
$self->{centreon_vmware_config}->{vsphere_server}->{$self->{whoaim}}->{pid} = $child_vpshere_pid;
$self->{centreon_vmware_config}->{vsphere_server}->{$self->{whoaim}}->{pid} = $child_vpshere_pid;
}
sub bind_ipc {
@ -577,21 +654,21 @@ sub run {
my $context = zmq_init();
$frontend = zmq_socket($context, ZMQ_ROUTER);
if (!defined($frontend)) {
$centreon_vmware->{logger}->writeLogError("Can't setup server: $!");
exit(1);
$centreon_vmware->{logger}->writeLogFatal("Can't setup server: $!");
}
zmq_setsockopt($frontend, ZMQ_LINGER, 0); # we discard
zmq_setsockopt($frontend, ZMQ_LINGER, 0); # we discard
zmq_bind($frontend, 'tcp://' . $centreon_vmware->{centreon_vmware_config}->{bind} . ':' . $centreon_vmware->{centreon_vmware_config}->{port});
$centreon_vmware->bind_ipc(socket => $frontend, ipc_file => $centreon_vmware->{centreon_vmware_config}->{ipc_file});
foreach (keys %{$centreon_vmware->{centreon_vmware_config}->{vsphere_server}}) {
$centreon_vmware->{counter_stats}->{$_} = 0;
$centreon_vmware->{logger}->writeLogDebug("Creating vSphere child for $_");
$centreon_vmware->create_vsphere_child(vsphere_name => $_, dynamic => 0);
}
$centreon_vmware->{logger}->writeLogInfo("[Server accepting clients]");
# Initialize poll set
$centreon_vmware->{poll} = [
{
@ -600,10 +677,10 @@ sub run {
callback => \&router_event
}
];
$centreon_vmware->{logger}->writeLogDebug("Global loop starting...");
# Switch messages between sockets
while (1) {
$centreon_vmware->check_childs();
$centreon_vmware->check_children();
zmq_poll($centreon_vmware->{poll}, 5000);
}
}
@ -611,3 +688,4 @@ sub run {
1;
__END__

View File

@ -0,0 +1,55 @@
#!/usr/bin/perl
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
use strict;
use warnings FATAL => 'all';
use JSON::XS;
use Data::Dumper;
die "Usage: centreon_vmware_convert_config_file /etc/centreon/centreon_vmware.pm > /etc/centreon/centreon_vmware.json" if (scalar(@ARGV) < 1);
my $config_file = $ARGV[0];
die "Config file $config_file does not exist.\n" if (! -f $config_file);
our %centreon_vmware_config;
require($config_file) or die "Error while loading file $config_file";
my $new_config_structure = {
vsphere_server => []
};
for my $config_entry_key (keys %centreon_vmware_config){
if ($config_entry_key eq 'vsphere_server') {
for my $server_config_entry_key (keys %{$centreon_vmware_config{vsphere_server}}) {
my $config_entry_content = $centreon_vmware_config{vsphere_server}->{$server_config_entry_key};
$config_entry_content->{name} = $server_config_entry_key;
push @{$new_config_structure->{vsphere_server}}, $config_entry_content;
}
} else {
$new_config_structure->{$config_entry_key} = $centreon_vmware_config{$config_entry_key};
}
}
my $new_json_config = encode_json($new_config_structure) or die "Unable to convert this object to JSON:\n" . Dumper($new_config_structure);
print($new_json_config);
exit(0);

View File

@ -0,0 +1,382 @@
#
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package centreon::script::centreonvault;
use strict;
use warnings;
use JSON::XS;
use MIME::Base64;
use Crypt::OpenSSL::AES;
use Net::Curl::Easy qw(:constants);
use centreon::vmware::common;
my $VAULT_PATH_REGEX = qr/^secret::hashicorp_vault::([^:]+)::(.+)$/;
sub new {
my ($class, %options) = @_;
my $self = bless \%options, $class;
# mandatory options:
# - logger: logger object
# - config_file: path of a JSON vault config file
$self->{enabled} = 1;
$self->{crypted_credentials} = 1;
if ( !$self->init() ) {
$self->{enabled} = 0;
$self->{logger}->writeLogError("An error occurred in init() method. Centreonvault cannot be used.");
}
return $self;
}
sub init {
my ($self, %options) = @_;
$self->check_options() or return undef;
# check if the following information is available
$self->{logger}->writeLogDebug("Reading Vault configuration from file " . $self->{config_file} . ".");
$self->{vault_config} = centreon::vmware::common::parse_json_file( 'json_file' => $self->{config_file} );
if (defined($self->{vault_config}->{error_message})) {
$self->{logger}->writeLogError("Error while parsing " . $self->{config_file} . ": "
. $self->{vault_config}->{error_message});
return undef;
}
$self->check_configuration() or return undef;
$self->{logger}->writeLogDebug("Vault configuration read. Name: " . $self->{vault_config}->{name}
. ". Url: " . $self->{vault_config}->{url} . ".");
# Create the Curl object, it will be used several times
$self->{curl_easy} = Net::Curl::Easy->new();
$self->{curl_easy}->setopt( CURLOPT_USERAGENT, "Centreon VMware daemon's centreonvault.pm");
return 1;
}
sub check_options {
my ($self, %options) = @_;
if ( !defined($self->{logger}) ) {
die "FATAL: No logger given to the constructor. Centreonvault cannot be used.";
}
if ( !defined($self->{config_file})) {
$self->{logger}->writeLogError("No config file given to the constructor. Centreonvault cannot be used.");
return undef;
}
if ( ! -f $self->{config_file} ) {
$self->{logger}->writeLogError("The given configuration file " . $self->{config_file}
. " does not exist. Centreonvault cannot be used.");
return undef;
}
return 1;
}
sub check_configuration {
my ($self, %options) = @_;
if ( !defined($self->{vault_config}->{url}) || $self->{vault_config}->{url} eq '') {
$self->{logger}->writeLogInfo("Vault url is missing from configuration.");
$self->{vault_config}->{url} = '127.0.0.1';
}
if ( !defined($self->{vault_config}->{port}) || $self->{vault_config}->{port} eq '') {
$self->{logger}->writeLogInfo("Vault port is missing from configuration.");
$self->{vault_config}->{port} = '443';
}
# Normally, the role_id and secret_id data are encrypted using AES wit the following information:
# firstKey = APP_SECRET (environment variable)
# secondKey = 'salt' (hashing) key given by vault.json configuration file
# both are base64 encoded
if ( !defined($self->{vault_config}->{salt}) || $self->{vault_config}->{salt} eq '') {
$self->{logger}->writeLogError("Vault environment does not seem complete: 'salt' attribute missing from "
. $self->{config_file}
. ". 'role_id' and 'secret_id' won't be decrypted, so they'll be used as they're stored in the vault config file.");
$self->{crypted_credentials} = 0;
$self->{hash_key} = '';
} else {
$self->{hash_key} = $self->{vault_config}->{salt}; # key for sha3-512 hmac
}
if ( !defined($ENV{'APP_SECRET'}) || $ENV{'APP_SECRET'} eq '' ) {
$self->{logger}->writeLogError("Vault environment does not seem complete. 'APP_SECRET' environment variable missing."
. " 'role_id' and 'secret_id' won't be decrypted, so they'll be used as they're stored in the vault config file.");
$self->{crypted_credentials} = 0;
$self->{encryption_key} = '';
} else {
$self->{encryption_key} = $ENV{'APP_SECRET'}; # key for aes-256-cbc
}
return 1;
}
sub extract_and_decrypt {
my ($self, %options) = @_;
my $input = decode_base64($options{data});
$self->{logger}->writeLogDebug("data to extract and decrypt: '" . $options{data} . "'");
# with AES-256, the IV length must 16 bytes
my $iv_length = 16;
# extract the IV, the hashed data, the encrypted data
my $iv = substr($input, 0, $iv_length); # initialization vector
my $hashed_data = substr($input, $iv_length, 64); # hmac of the original data, for integrity control
my $encrypted_data = substr($input, $iv_length + 64); # data to decrypt
# create the AES object
$self->{logger}->writeLogDebug(
"Creating the AES decryption object for initialization vector (IV) of length "
. length($iv) . "B, key of length " . length($self->{encryption_key}) . "B."
);
my $cipher;
eval {
$cipher = Crypt::OpenSSL::AES->new(
decode_base64( $self->{encryption_key} ),
{
'cipher' => 'AES-256-CBC',
'iv' => $iv,
'padding' => 1
}
);
};
if ($@) {
$self->{logger}->writeLogError("There was an error while creating the AES object: " . $@);
return undef;
}
# decrypt
$self->{logger}->writeLogDebug("Decrypting the data of length " . length($encrypted_data) . "B.");
my $decrypted_data;
eval {$decrypted_data = $cipher->decrypt($encrypted_data);};
if ($@) {
$self->{logger}->writeLogError("There was an error while decrypting one of the AES-encrypted data: " . $@);
return undef;
}
return $decrypted_data;
}
sub authenticate {
my ($self) = @_;
# initial value: assuming the role and secret id might not be encrypted
my $role_id = $self->{vault_config}->{role_id};
my $secret_id = $self->{vault_config}->{secret_id};
if ($self->{crypted_credentials}) {
# Then decrypt using https://github.com/perl-openssl/perl-Crypt-OpenSSL-AES
# keep the decrypted data in local variables so that they stay in memory for as little time as possible
$self->{logger}->writeLogDebug("Decrypting the credentials needed to authenticate to the vault.");
$role_id = $self->extract_and_decrypt( ('data' => $role_id ));
$secret_id = $self->extract_and_decrypt( ('data' => $secret_id ));
$self->{logger}->writeLogDebug("role_id and secret_id have been decrypted.");
} else {
$self->{logger}->writeLogDebug("role_id and secret_id are not crypted");
}
# Authenticate to get the token
my $url = "https://" . $self->{vault_config}->{url} . ":" . $self->{vault_config}->{port} . "/v1/auth/approle/login";
$self->{logger}->writeLogDebug("Authenticating to the vault server at URL: $url");
$self->{curl_easy}->setopt( CURLOPT_URL, $url );
my $post_data = "role_id=$role_id&secret_id=$secret_id";
my $auth_result_json;
# to get more details (in STDERR)
#$self->{curl_easy}->setopt(CURLOPT_VERBOSE, 1);
$self->{curl_easy}->setopt(CURLOPT_POST, 1);
$self->{curl_easy}->setopt(CURLOPT_POSTFIELDS, $post_data);
$self->{curl_easy}->setopt(CURLOPT_POSTFIELDSIZE, length($post_data));
$self->{curl_easy}->setopt(CURLOPT_WRITEDATA(), \$auth_result_json);
eval {
$self->{curl_easy}->perform();
};
if ($@) {
$self->{logger}->writeLogError("Error while authenticating to the vault: " . $@);
return undef;
}
$self->{logger}->writeLogInfo("Authentication to the vault passed." );
my $auth_result_obj = centreon::vmware::common::transform_json_to_object($auth_result_json);
if (defined($auth_result_obj->{error_message})) {
$self->{logger}->writeLogError("Error while decoding JSON '$auth_result_json'. Message: "
. $auth_result_obj->{error_message});
return undef;
}
# store the token (.auth.client_token) and its expiration date (current date + .lease_duration)
my $expiration_epoch = -1;
my $lease_duration = $auth_result_obj->{auth}->{lease_duration};
if ( defined($lease_duration)
&& $lease_duration =~ /\d+/
&& $lease_duration > 0 ) {
$expiration_epoch = time() + $lease_duration;
}
$self->{auth} = {
'token' => $auth_result_obj->{auth}->{client_token},
'expiration_epoch' => $expiration_epoch
};
$self->{logger}->writeLogInfo("Authenticating worked. Token valid until "
. localtime($self->{auth}->{expiration_epoch}));
return 1;
}
sub is_token_still_valid {
my ($self) = @_;
if (
!defined($self->{auth})
|| !defined($self->{auth}->{token})
|| $self->{auth}->{token} eq ''
|| $self->{auth}->{expiration_epoch} <= time()
) {
$self->{logger}->writeLogInfo("The token has expired or is invalid.");
return undef;
}
$self->{logger}->writeLogDebug("The token is still valid.");
return 1;
}
sub get_secret {
my ($self, $secret) = @_;
# if vault not enabled, return the secret unchanged
return $secret if ( ! $self->{enabled});
my ($secret_path, $secret_name) = $secret =~ $VAULT_PATH_REGEX;
if (!defined($secret_path) || !defined($secret_name)) {
$self->{logger}->writeLogInfo("A string given to get_secret does not look like a secret. Using it as a plain text credential?");
return $secret;
}
$self->{logger}->writeLogDebug("Secret path: $secret_path - Secret name: $secret_name");
if (!defined($self->{auth}) || !$self->is_token_still_valid() ) {
$self->authenticate() or return $secret;
}
# prepare the GET statement
my $get_result_json;
my $url = "https://" . $self->{vault_config}->{url} . ":" . $self->{vault_config}->{port} . "/v1/" . $secret_path;
$self->{logger}->writeLogDebug("Requesting URL: $url");
#$self->{curl_easy}->setopt( CURLOPT_VERBOSE, 1 );
$self->{curl_easy}->setopt( CURLOPT_URL, $url );
$self->{curl_easy}->setopt( CURLOPT_POST, 0 );
$self->{curl_easy}->setopt( CURLOPT_WRITEDATA(), \$get_result_json );
$self->{curl_easy}->setopt( CURLOPT_HTTPHEADER(), ["X-Vault-Token: " . $self->{auth}->{token}]);
eval {
$self->{curl_easy}->perform();
};
if ($@) {
$self->{logger}->writeLogError("Error while getting a secret from the vault: " . $@);
return $secret;
}
$self->{logger}->writeLogDebug("Request passed.");
# request_id
# the result is a json string, convert it into an object
my $get_result_obj = centreon::vmware::common::transform_json_to_object($get_result_json);
if (defined($get_result_obj->{error_message})) {
$self->{logger}->writeLogError("Error while decoding JSON '$get_result_json'. Message: "
. $get_result_obj->{error_message});
return $secret;
}
$self->{logger}->writeLogDebug("Request id is " . $get_result_obj->{request_id});
# .data.data will contain the stored macros
if ( !defined($get_result_obj->{data})
|| !defined($get_result_obj->{data}->{data})
|| !defined($get_result_obj->{data}->{data}->{$secret_name}) ) {
$self->{logger}->writeLogError("Could not get secret '$secret_name' from path '$secret_path' from the vault. Enable debug for more details.");
$self->{logger}->writeLogDebug("Response: " . $get_result_json);
return $secret;
}
$self->{logger}->writeLogInfo("Secret '$secret_name' from path '$secret_path' retrieved from the vault.");
return $get_result_obj->{data}->{data}->{$secret_name};
}
1;
__END__
=head1 NAME
Centreon Vault password manager
=head1 SYNOPSIS
Allows to retrieve secrets (usually username and password) from a Hashicorp vault compatible api given a config file as constructor.
use centreon::vmware::logger;
use centreon::script::centreonvault;
my $vault = centreon::script::centreonvault->new(
(
'logger' => centreon::vmware::logger->new(),
'config_file' => '/var/lib/centreon/vault/vault.json'
)
);
my $password = $vault->get_secret('secret::hashicorp_vault::mypath/to/mysecrets::password');
=head1 METHODS
=head2 new(\%options)
Constructor of the vault object.
%options must provide:
- logger: an object of the centreon::vmware::logger class.
- config_file: full path and file name of the Centreon Vault JSON config file.
The default config_file path should be '/var/lib/centreon/vault/vault.json'.
The expected file format for Centreon Vault is:
{
"name": "hashicorp_vault",
"url": "vault-server.mydomain.com",
"salt": "<base64 encoded(<32 bytes long key used to hash the crypted data)>",
"port": 443,
"root_path": "vmware_daemon",
"role_id": "<base64 encoded(<iv><hmac_hash><encrypted_role_id>)",
"secret_id": "<base64 encoded(<iv><hmac_hash><encrypted_secret_id>)"
}
=head2 get_secret($secret)
Returns the secret stored in the Centreon Vault at the given path.
If the format of the secret does not match the regular expression
C</^secret::hashicorp_vault::([^:]+)::(.+)$/>
or in case of any failure in the process, the method will return the secret unchanged.
=cut

View File

@ -1,5 +1,5 @@
#
# Copyright 2019 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,5 +1,5 @@
#
# Copyright 2019 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
@ -162,19 +162,22 @@ sub run {
push @$customValuesEsx, { key => $customFields->{ $_->{key} }, value => $_->{value} };
}
}
$esx{type} = 'esx';
$esx{name} = $esx->name;
$esx{os} = $esx->{'config.product.productLineId'} . ' ' . $esx->{'config.product.version'};
$esx{hardware} = $esx->{'hardware.systemInfo.vendor'} . ' ' . $esx->{'hardware.systemInfo.model'};
$esx{power_state} = $esx->{'runtime.powerState'}->val;
$esx{connection_state} = $esx->{'runtime.connectionState'}->val;
$esx{maintenance} = $esx->{'runtime.inMaintenanceMode'};
$esx{datacenter} = $datacenter->name;
$esx{cluster} = $cluster->name;
$esx{type} = 'esx';
$esx{name} = $esx->name;
$esx{hardware} = $esx->{'hardware.systemInfo.vendor'} . ' ' . $esx->{'hardware.systemInfo.model'};
$esx{power_state} = $esx->{'runtime.powerState'}->val;
$esx{connection_state} = $esx->{'runtime.connectionState'}->val;
$esx{maintenance} = $esx->{'runtime.inMaintenanceMode'};
$esx{datacenter} = $datacenter->name;
$esx{cluster} = $cluster->name;
$esx{custom_attributes} = $customValuesEsx;
$esx{tags} = [];
if (defined($tags)) {
$esx{tags} = $tags->{esx}->{ $esx->{mo_ref}->{value} } if (defined($tags->{esx}->{ $esx->{mo_ref}->{value} }));
$esx{tags} = [];
$esx{os} = defined($esx->{'config.product.productLineId'}) ? $esx->{'config.product.productLineId'} . ' ' : ''
. defined($esx->{'config.product.version'}) ? $esx->{'config.product.version'} : '';
if (defined($tags) and defined($tags->{esx}->{ $esx->{mo_ref}->{value} })) {
$esx{tags} = $tags->{esx}->{ $esx->{mo_ref}->{value} };
}
foreach my $nic (@{$esx->{'config.virtualNicManagerInfo.netConfig'}}) {

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
@ -25,7 +25,7 @@ use VMware::VIRuntime;
use VMware::VILib;
use ZMQ::LibZMQ4;
use ZMQ::Constants qw(:all);
use JSON::XS;;
use JSON::XS;
my $manager_display = {};
my $manager_response = {};
@ -794,4 +794,38 @@ sub vsan_get_performances {
return $result;
}
sub transform_json_to_object {
my ($json_data) = @_;
my $json_as_object;
eval {
$json_as_object = decode_json($json_data);
};
if ($@) {
return ('error_message' => "Could not decode JSON from '$json_data'. Reason: " . $@);
};
return($json_as_object);
}
sub parse_json_file {
my (%options) = @_;
my $fh;
my $json_data = '';
if ( !defined($options{json_file}) ) {
return ('error_message' => "parse_json_file: json_file option is mandatory");
}
my $json_file = $options{json_file};
open($fh, '<', $json_file) or return ('error_message' => "parse_json_file: Cannot open " . $json_file);
for my $line (<$fh>) {
chomp $line;
$json_data .= $line;
}
close($fh);
return transform_json_to_object($json_data);
}
1;

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
@ -237,7 +237,7 @@ sub run {
my ($connector) = shift;
my $timeout_process = 0;
$connector->{logger}->writeLogInfo("'" . $connector->{whoaim} . "' init begin");
$connector->{logger}->writeLogInfo("'" . $connector->{whoaim} . "' ZMQ init begin");
my $context = zmq_init();
$backend = zmq_socket($context, ZMQ_DEALER);

View File

@ -1,5 +1,5 @@
#
# Copyright 2019 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,5 +1,5 @@
#
# Copyright 2019 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,5 +1,5 @@
#
# Copyright 2019 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,5 +1,5 @@
#
# Copyright 2019 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,5 +1,5 @@
#
# Copyright 2019 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
@ -50,9 +50,18 @@ use warnings;
use Sys::Syslog qw(:standard :macros);
use IO::Handle;
my %severities = (1 => LOG_INFO,
2 => LOG_ERR,
4 => LOG_DEBUG);
my %syslog_severities = (
1 => LOG_CRIT,
2 => LOG_ERR,
4 => LOG_INFO,
5 => LOG_DEBUG
);
my %human_severities = (
1 => 'fatal',
2 => 'error',
4 => 'info',
5 => 'debug'
);
sub new {
my $class = shift;
@ -62,8 +71,8 @@ sub new {
file => 0,
filehandler => undef,
# 0 = nothing, 1 = critical, 3 = info, 7 = debug
severity => 3,
old_severity => 3,
severity => 4,
old_severity => 4,
# 0 = stdout, 1 = file, 2 = syslog
log_mode => 0,
# Output pid of current process
@ -104,7 +113,7 @@ sub is_file_mode {
sub is_debug {
my $self = shift;
if (($self->{severity} & 4) == 0) {
if ($self->{severity} < 5) {
return 0;
}
return 1;
@ -138,21 +147,22 @@ sub set_default_severity {
# Getter/Setter Log severity
sub severity {
my $self = shift;
if (@_) {
my $save_severity = $self->{severity};
if ($_[0] =~ /^[012347]$/) {
if ($_[0] =~ /^[01245]$/) {
$self->{severity} = $_[0];
} elsif ($_[0] eq "none") {
$self->{severity} = 0;
} elsif ($_[0] eq "error") {
$self->{severity} = 1;
$self->{severity} = 2;
} elsif ($_[0] eq "info") {
$self->{severity} = 3;
$self->{severity} = 4;
} elsif ($_[0] eq "debug") {
$self->{severity} = 7;
$self->{severity} = 5;
} else {
$self->writeLogError("Wrong severity value set.");
return -1;
$self->writeLogError("Wrong severity value given: " . $_[0] . ". Keeping default value: " . $self->{severity});
return $self->{severity};
}
$self->{old_severity} = $save_severity;
}
@ -176,14 +186,18 @@ sub get_date {
sub writeLog($$$%) {
my ($self, $severity, $msg, %options) = @_;
my $withdate = (defined $options{withdate}) ? $options{withdate} : 1;
$msg = ($self->{withpid} == 1) ? "$$ - $msg " : $msg;
my $newmsg = ($withdate)
? $self->get_date . " - $msg" : $msg;
if (($self->{severity} & $severity) == 0) {
return;
}
# do nothing if the configured severity does not imply logging this message
return if ($self->{severity} < $severity);
my $withdate = (defined $options{withdate}) ? $options{withdate} : 1;
$msg = ($self->{withpid} == 1) ? "[$$] $msg " : $msg;
my $newmsg = ($withdate)
? "[" . $self->get_date . "] " : '';
$newmsg .= "[" . $human_severities{$severity} . "] " . $msg;
# Bit mask: if AND gives 0 it means the log level does not require this message to be logged
if ($self->{log_mode} == 0) {
print "$newmsg\n";
} elsif ($self->{log_mode} == 1) {
@ -191,20 +205,24 @@ sub writeLog($$$%) {
print { $self->{filehandler} } "$newmsg\n";
}
} elsif ($self->{log_mode} == 2) {
syslog($severities{$severity}, $msg);
syslog($syslog_severities{$severity}, $msg);
}
}
sub writeLogDebug {
shift->writeLog(4, @_);
shift->writeLog(5, @_);
}
sub writeLogInfo {
shift->writeLog(2, @_);
shift->writeLog(4, @_);
}
sub writeLogError {
shift->writeLog(2, @_);
}
sub writeLogFatal {
shift->writeLog(1, @_);
die("FATAL: " . $_[0] . "\n");
}
sub DESTROY {

View File

@ -1,4 +1,4 @@
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
@ -46,9 +46,9 @@ sub new {
$self->{name} = $name;
$self->{logger} = centreon::vmware::logger->new();
$self->{options} = {
"logfile=s" => \$self->{log_file},
"logfile=s" => \$self->{log_file},
"severity=s" => \$self->{severity},
"help|?" => \$self->{help}
"help|?" => \$self->{help}
};
return $self;
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/perl
# Copyright 2015 Centreon (http://www.centreon.com/)
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
@ -42,6 +42,10 @@ centreon_vmware.pl [options]
Specify the path to the centreon_vmware configuration file (default: /etc/centreon/centreon_vmware.pm).
=item B<--vault-config>
Full path to the file defining access to the Centreon vault (/etc/centreon-engine/centreonvault.json by default).
=item B<--help>
Print a brief help message and exits.
@ -51,6 +55,6 @@ Print a brief help message and exits.
=head1 DESCRIPTION
B<centreon_vmware.pl> will connect to ESX and/or VirtualCenter.
Use the plugin 'apps::vmware::connector::plugin' from: https://github.com/centreon/centreon-plugins
To be used with the plugin 'apps::vmware::connector::plugin' from: https://github.com/centreon/centreon-plugins
=cut

View File

@ -0,0 +1,43 @@
#!/usr/bin/perl
use strict;
use warnings;
use Test2::V0;
use Test2::Plugin::NoWarnings echo => 1;
use FindBin;
use lib qw($FindBin::RealBin/../../../src);
use centreon::script::centreonvault;
use centreon::vmware::logger;
my $vault;
my $global_logger = centreon::vmware::logger->new();
my @test_data = (
{'logger' => undef, 'config_file' => undef, 'test' => '$error_message =~ /FATAL: No logger given to the constructor/'},
{'logger' => $global_logger, 'config_file' => undef, 'test' => '$vault->{enabled} == 0'},
{'logger' => $global_logger, 'config_file' => 'does_not_exist.json', 'test' => '$vault->{enabled} == 0'}
);
for my $i (0..$#test_data) {
my $logger = $test_data[$i]->{logger};
my $config_file = $test_data[$i]->{config_file};
my $test = $test_data[$i]->{test};
use Data::Dumper;
#print("Test $i with logger " . Dumper($logger) ."\n");
eval {
$vault = centreon::script::centreonvault->new(
(
'logger' => $logger,
'config_file' => $config_file
)
);
};
my $error_message = defined($@) ? $@ : '';
print("Test $i with vault " . Dumper($vault) ."\n");
ok (eval($test), "TEST CASE $i FAILED: '$test' with error message: '" . $error_message . "'" );
}
done_testing();