enh(vmware/connector): see details (#3330)

- add modes: cpu-cluster, licences, storage-host
- mode datastore-iops: add total iops counters
- mode datastore-usage: add --refresh option
- add option --empty-continue for modes: snapshot-vm, tools-vm
- fix --time-shift option: now it's working
This commit is contained in:
qgarnier 2021-12-21 11:42:14 +01:00 committed by GitHub
parent 3bd6dbcbc7
commit 7bfa19a37e
13 changed files with 1269 additions and 214 deletions

View File

@ -86,7 +86,7 @@ sub check_options {
$self->{vsphere_username} = (defined($self->{option_results}->{vsphere_username})) ? shift(@{$self->{option_results}->{vsphere_username}}) : undef; $self->{vsphere_username} = (defined($self->{option_results}->{vsphere_username})) ? shift(@{$self->{option_results}->{vsphere_username}}) : undef;
$self->{vsphere_password} = (defined($self->{option_results}->{vsphere_password})) ? shift(@{$self->{option_results}->{vsphere_password}}) : undef; $self->{vsphere_password} = (defined($self->{option_results}->{vsphere_password})) ? shift(@{$self->{option_results}->{vsphere_password}}) : undef;
$self->{sampling_period} = (defined($self->{option_results}->{sampling_period})) ? shift(@{$self->{option_results}->{sampling_period}}) : undef; $self->{sampling_period} = (defined($self->{option_results}->{sampling_period})) ? shift(@{$self->{option_results}->{sampling_period}}) : undef;
$self->{time_shift} = (defined($self->{option_results}->{sampling_period})) ? shift(@{$self->{option_results}->{time_shift}}) : 0; $self->{time_shift} = (defined($self->{option_results}->{time_shift})) ? shift(@{$self->{option_results}->{time_shift}}) : 0;
$self->{unknown_connector_status} = (defined($self->{option_results}->{unknown_connector_status})) ? $self->{option_results}->{unknown_connector_status} : '%{code} < 0 || (%{code} > 0 && %{code} < 200)'; $self->{unknown_connector_status} = (defined($self->{option_results}->{unknown_connector_status})) ? $self->{option_results}->{unknown_connector_status} : '%{code} < 0 || (%{code} > 0 && %{code} < 200)';
$self->{warning_connector_status} = (defined($self->{option_results}->{warning_connector_status})) ? $self->{option_results}->{warning_connector_status} : ''; $self->{warning_connector_status} = (defined($self->{option_results}->{warning_connector_status})) ? $self->{option_results}->{warning_connector_status} : '';
$self->{critical_connector_status} = (defined($self->{option_results}->{critical_connector_status})) ? $self->{option_results}->{critical_connector_status} : ''; $self->{critical_connector_status} = (defined($self->{option_results}->{critical_connector_status})) ? $self->{option_results}->{critical_connector_status} : '';
@ -221,7 +221,7 @@ sub strip_cr {
sub execute { sub execute {
my ($self, %options) = @_; my ($self, %options) = @_;
$self->add_params(%options); $self->add_params(%options);
# Build request # Build request

View File

@ -0,0 +1,142 @@
#
# Copyright 2021 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 apps::vmware::connector::mode::cpucluster;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
sub prefix_cluster_output {
my ($self, %options) = @_;
return "Cluster '" . $options{instance} . "' : ";
}
sub cluster_long_output {
my ($self, %options) = @_;
return "checking cluster '" . $options{instance} . "'";
}
sub prefix_cpu_output {
my ($self, %options) = @_;
return "cpu total average: ";
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'clusters', type => 3, cb_prefix_output => 'prefix_cluster_output', cb_long_output => 'cluster_long_output', indent_long_output => ' ', message_multiple => 'All clusters are ok',
group => [
{ name => 'cpu', cb_prefix_output => 'prefix_cpu_output', type => 0, skipped_code => { -10 => 1 } }
]
}
];
$self->{maps_counters}->{cpu} = [
{ label => 'total-cpu', nlabel => 'cluster.cpu.utilization.percentage', set => {
key_values => [ { name => 'cpu_average' } ],
output_template => '%s %%',
perfdatas => [
{ template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1 }
]
}
},
{ label => 'total-cpu-mhz', nlabel => 'cluster.cpu.utilization.mhz', set => {
key_values => [ { name => 'cpu_average_mhz' } ],
output_template => '%s MHz',
perfdatas => [
{ template => '%s', unit => 'MHz', min => 0, label_extra_instance => 1 }
]
}
}
];
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'cluster-name:s' => { name => 'cluster_name' },
'filter' => { name => 'filter' },
'scope-datacenter:s' => { name => 'scope_datacenter' }
});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
$self->{host} = {};
my $response = $options{custom}->execute(
params => $self->{option_results},
command => 'cpucluster'
);
$self->{clusters} = {};
foreach my $cluster_id (keys %{$response->{data}}) {
my $cluster_name = $response->{data}->{$cluster_id}->{name};
$self->{clusters}->{$cluster_name} = {
cpu => {
cpu_average => $response->{data}->{$cluster_id}->{'cpu.usage.average'},
cpu_average_mhz => $response->{data}->{$cluster_id}->{'cpu.usagemhz.average'}
}
};
}
}
1;
__END__
=head1 MODE
Check cluster cpu usage.
=over 8
=item B<--cluster-name>
cluster to check.
If not set, we check all clusters.
=item B<--filter>
Cluster name is a regexp.
=item B<--scope-datacenter>
Search in following datacenter(s) (can be a regexp).
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'total-cpu', 'total-cpu-mhz'.
=back
=cut

View File

@ -52,7 +52,7 @@ sub set_counters {
] ]
} }
]; ];
$self->{maps_counters}->{global} = [ $self->{maps_counters}->{global} = [
{ {
label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i',
@ -86,7 +86,7 @@ sub set_counters {
} }
} }
]; ];
$self->{maps_counters}->{cpu} = [ $self->{maps_counters}->{cpu} = [
{ label => 'cpu', nlabel => 'host.core.cpu.utilization.percentage', set => { { label => 'cpu', nlabel => 'host.core.cpu.utilization.percentage', set => {
key_values => [ { name => 'cpu_usage' }, { name => 'display' } ], key_values => [ { name => 'cpu_usage' }, { name => 'display' } ],

View File

@ -33,20 +33,64 @@ sub custom_status_output {
return 'accessible ' . $self->{result_values}->{accessible}; return 'accessible ' . $self->{result_values}->{accessible};
} }
sub prefix_datastore_output {
my ($self, %options) = @_;
return "Datastore '" . $options{instance_value}->{display} . "' : ";
}
sub datastore_long_output {
my ($self, %options) = @_;
return "checking datastore '" . $options{instance_value}->{display} . "'";
}
sub prefix_vm_output {
my ($self, %options) = @_;
return "virtual machine '" . $options{instance_value}->{display} . "' ";
}
sub prefix_global_iops_output {
my ($self, %options) = @_;
return 'Total ';
}
sub set_counters { sub set_counters {
my ($self, %options) = @_; my ($self, %options) = @_;
$self->{maps_counters_type} = [ $self->{maps_counters_type} = [
{ name => 'global_iops', type => 0, cb_prefix_output => 'prefix_global_iops_output', skipped_code => { -10 => 1 } },
{ name => 'datastore', type => 3, cb_prefix_output => 'prefix_datastore_output', cb_long_output => 'datastore_long_output', indent_long_output => ' ', message_multiple => 'All datastores are ok', { name => 'datastore', type => 3, cb_prefix_output => 'prefix_datastore_output', cb_long_output => 'datastore_long_output', indent_long_output => ' ', message_multiple => 'All datastores are ok',
group => [ group => [
{ name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'ds_global', type => 0, skipped_code => { -10 => 1 } },
{ name => 'global_iops', type => 0, skipped_code => { -10 => 1 } }, { name => 'ds_global_iops', type => 0, skipped_code => { -10 => 1 } },
{ name => 'vm', cb_prefix_output => 'prefix_vm_output', message_multiple => 'All virtual machines IOPs are ok', type => 1, skipped_code => { -10 => 1 } } { name => 'vm', cb_prefix_output => 'prefix_vm_output', message_multiple => 'All virtual machines IOPs are ok', type => 1, skipped_code => { -10 => 1 } }
] ]
} }
]; ];
$self->{maps_counters}->{global} = [ $self->{maps_counters}->{global_iops} = [
{ label => 'read-total', nlabel => 'datastores.read.usage.iops', set => {
key_values => [ { name => 'read' } ],
output_template => 'read: %s iops',
perfdatas => [
{ label => 'total_riops', template => '%s', unit => 'iops', min => 0 }
]
}
},
{ label => 'write-total', nlabel => 'datastores.write.usage.iops', set => {
key_values => [ { name => 'write' } ],
output_template => 'write: %s iops',
perfdatas => [
{ label => 'total_wiops', template => '%s', unit => 'iops', min => 0 }
]
}
}
];
$self->{maps_counters}->{ds_global} = [
{ {
label => 'status', type => 2, unknown_default => '%{accessible} !~ /^true|1$/i', label => 'status', type => 2, unknown_default => '%{accessible} !~ /^true|1$/i',
set => { set => {
@ -58,7 +102,7 @@ sub set_counters {
} }
]; ];
$self->{maps_counters}->{global_iops} = [ $self->{maps_counters}->{ds_global_iops} = [
{ label => 'read', nlabel => 'datastore.read.usage.iops', set => { { label => 'read', nlabel => 'datastore.read.usage.iops', set => {
key_values => [ { name => 'read' } ], key_values => [ { name => 'read' } ],
output_template => '%s read iops', output_template => '%s read iops',
@ -101,24 +145,6 @@ sub set_counters {
]; ];
} }
sub prefix_datastore_output {
my ($self, %options) = @_;
return "Datastore '" . $options{instance_value}->{display} . "' : ";
}
sub datastore_long_output {
my ($self, %options) = @_;
return "checking datastore '" . $options{instance_value}->{display} . "'";
}
sub prefix_vm_output {
my ($self, %options) = @_;
return "virtual machine '" . $options{instance_value}->{display} . "' ";
}
sub new { sub new {
my ($class, %options) = @_; my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options); my $self = $class->SUPER::new(package => __PACKAGE__, %options);
@ -152,24 +178,28 @@ sub manage_selection {
$self->{output}->exit(); $self->{output}->exit();
} }
$self->{global_iops} = { write => 0, read => 0 };
foreach my $ds_id (keys %{$response->{data}}) { foreach my $ds_id (keys %{$response->{data}}) {
my $ds_name = $response->{data}->{$ds_id}->{name}; my $ds_name = $response->{data}->{$ds_id}->{name};
$self->{datastore}->{$ds_name} = { display => $ds_name, $self->{datastore}->{$ds_name} = { display => $ds_name,
vm => {}, vm => {},
global => { ds_global => {
accessible => $response->{data}->{$ds_id}->{accessible}, accessible => $response->{data}->{$ds_id}->{accessible}
}, },
global_iops => { ds_global_iops => {
write => $response->{data}->{$ds_id}->{'disk.numberWrite.summation'}, write => $response->{data}->{$ds_id}->{'disk.numberWrite.summation'},
read => $response->{data}->{$ds_id}->{'disk.numberRead.summation'}, read => $response->{data}->{$ds_id}->{'disk.numberRead.summation'}
}, }
}; };
$self->{global_iops}->{write} += $response->{data}->{$ds_id}->{'disk.numberWrite.summation'};
$self->{global_iops}->{read} += $response->{data}->{$ds_id}->{'disk.numberRead.summation'};
foreach my $vm_name (sort keys %{$response->{data}->{$ds_id}->{vm}}) { foreach my $vm_name (sort keys %{$response->{data}->{$ds_id}->{vm}}) {
$self->{datastore}->{$ds_name}->{vm}->{$vm_name} = { $self->{datastore}->{$ds_name}->{vm}->{$vm_name} = {
display => $vm_name, display => $vm_name,
write => $response->{data}->{$ds_id}->{vm}->{$vm_name}->{'disk.numberWrite.summation'}, write => $response->{data}->{$ds_id}->{vm}->{$vm_name}->{'disk.numberWrite.summation'},
read => $response->{data}->{$ds_id}->{vm}->{$vm_name}->{'disk.numberRead.summation'}, read => $response->{data}->{$ds_id}->{vm}->{$vm_name}->{'disk.numberRead.summation'}
}; };
} }
} }
@ -216,15 +246,11 @@ Can used special variables like: %{accessible}
Set critical threshold for status (Default: ''). Set critical threshold for status (Default: '').
Can used special variables like: %{accessible} Can used special variables like: %{accessible}
=item B<--warning-*> =item B<--warning-*> B<--critical-*>
Threshold warning. Thresholds.
Can be: 'read', 'write', 'read-vm', 'write-vm'. Can be: 'read-total', 'write-total',
'read', 'write', 'read-vm', 'write-vm'.
=item B<--critical-*>
Threshold critical.
Can be: 'read', 'write', 'read-vm', 'write-vm'.
=back =back

View File

@ -151,7 +151,8 @@ sub new {
'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' },
'filter-host:s' => { name => 'filter_host' }, 'filter-host:s' => { name => 'filter_host' },
'units:s' => { name => 'units', default => '' }, 'units:s' => { name => 'units', default => '' },
'free' => { name => 'free' } 'free' => { name => 'free' },
'refresh' => { name => 'refresh' }
}); });
return $self; return $self;
@ -259,6 +260,10 @@ Search in following datacenter(s) (can be a regexp).
Filter datastores attached to hosts (can be a regexp). Filter datastores attached to hosts (can be a regexp).
=item B<--refresh>
Explicitly ask vmware to refreshes free-space and capacity values (slower).
=item B<--unknown-status> =item B<--unknown-status>
Set warning threshold for status (Default: '%{accessible} !~ /^true|1$/i'). Set warning threshold for status (Default: '%{accessible} !~ /^true|1$/i').

View File

@ -51,91 +51,6 @@ sub custom_summary_output {
return $msg; return $msg;
} }
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'global', type => 0, skipped_code => { -10 => 1 } },
{ name => 'host', type => 3, cb_prefix_output => 'prefix_host_output', cb_long_output => 'host_long_output', indent_long_output => ' ', message_multiple => 'All ESX hosts are ok',
group => [
{ name => 'global_host', type => 0, skipped_code => { -10 => 1 } },
{ name => 'global_problems', type => 0, skipped_code => { -10 => 1 } },
{ name => 'global_summary', type => 1 }
]
}
];
$self->{maps_counters}->{global} = [
{ label => 'total-problems', nlabel => 'host.health.problems.current.count', set => {
key_values => [ { name => 'total_problems' }, { name => 'total' } ],
output_template => '%s total health issue(s) found',
perfdatas => [
{ label => 'total_problems', template => '%s',
min => 0, max => 'total' }
]
}
}
];
$self->{maps_counters}->{global_host} = [
{
label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i',
set => {
key_values => [ { name => 'state' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold_ng
}
}
];
$self->{maps_counters}->{global_problems} = [
{ label => 'ok', threshold => 0, set => {
key_values => [ { name => 'ok' } ],
output_template => '%s health checks are green',
closure_custom_perfdata => sub { return 0; },
}
},
{ label => 'problems', nlabel => 'host.health.problems.current.count', set => {
key_values => [ { name => 'total_problems' }, { name => 'total' } ],
output_template => '%s total health issue(s) found',
perfdatas => [
{ label => 'problems', template => '%s',
min => 0, max => 'total', label_extra_instance => 1 }
]
}
},
{ label => 'problems-yellow', nlabel => 'host.health.yellow.current.count', set => {
key_values => [ { name => 'yellow' }, { name => 'total' } ],
output_template => '%s yellow health issue(s) found',
perfdatas => [
{ label => 'problems_yellow', template => '%s',
min => 0, max => 'total', label_extra_instance => 1 }
]
}
},
{ label => 'problems-red', nlabel => 'host.health.red.current.count', set => {
key_values => [ { name => 'red' }, { name => 'total' } ],
output_template => '%s red health issue(s) found',
perfdatas => [
{ label => 'problems_red', template => '%s',
min => 0, max => 'total', label_extra_instance => 1 }
]
}
},
];
$self->{maps_counters}->{global_summary} = [
{ label => 'global-summary', threshold => 0, set => {
key_values => [ { name => 'type' }, { name => 'name' }, { name => 'summary' } ],
closure_custom_output => $self->can('custom_summary_output'),
closure_custom_perfdata => sub { return 0; }
}
}
];
}
sub prefix_host_output { sub prefix_host_output {
my ($self, %options) = @_; my ($self, %options) = @_;
@ -160,9 +75,144 @@ sub prefix_cpu_output {
return "cpu '" . $options{instance_value}->{display} . "' "; return "cpu '" . $options{instance_value}->{display} . "' ";
} }
sub prefix_sensor_output {
my ($self, %options) = @_;
return "sensor '" . $options{instance} . "' ";
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'global', type => 0, skipped_code => { -10 => 1 } },
{ name => 'host', type => 3, cb_prefix_output => 'prefix_host_output', cb_long_output => 'host_long_output', indent_long_output => ' ', message_multiple => 'All ESX hosts are ok',
group => [
{ name => 'global_host', type => 0, skipped_code => { -10 => 1 } },
{ name => 'global_problems', type => 0, skipped_code => { -10 => 1 } },
{ name => 'global_summary', type => 1 },
{ name => 'sensors_temp', display_long => 1, cb_prefix_output => 'prefix_sensor_output', message_multiple => 'temperature sensors are ok', type => 1, skipped_code => { -10 => 1 } },
{ name => 'sensors_fan', display_long => 1, cb_prefix_output => 'prefix_sensor_output', message_multiple => 'fan sensors are ok', type => 1, skipped_code => { -10 => 1 } },
{ name => 'sensors_voltage', display_long => 1, cb_prefix_output => 'prefix_sensor_output', message_multiple => 'voltage sensors are ok', type => 1, skipped_code => { -10 => 1 } },
{ name => 'sensors_power', display_long => 1, cb_prefix_output => 'prefix_sensor_output', message_multiple => 'power sensors are ok', type => 1, skipped_code => { -10 => 1 } }
]
}
];
$self->{maps_counters}->{global} = [
{ label => 'total-problems', nlabel => 'host.health.problems.current.count', set => {
key_values => [ { name => 'total_problems' }, { name => 'total' } ],
output_template => '%s total health issue(s) found',
perfdatas => [
{ template => '%s', min => 0, max => 'total' }
]
}
}
];
$self->{maps_counters}->{global_host} = [
{
label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i',
set => {
key_values => [ { name => 'state' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold_ng
}
}
];
$self->{maps_counters}->{global_problems} = [
{ label => 'ok', threshold => 0, set => {
key_values => [ { name => 'ok' } ],
output_template => '%s health checks are green',
closure_custom_perfdata => sub { return 0; }
}
},
{ label => 'problems', nlabel => 'host.health.problems.current.count', set => {
key_values => [ { name => 'total_problems' }, { name => 'total' } ],
output_template => '%s total health issue(s) found',
perfdatas => [
{ template => '%s', min => 0, max => 'total', label_extra_instance => 1 }
]
}
},
{ label => 'problems-yellow', nlabel => 'host.health.yellow.current.count', set => {
key_values => [ { name => 'yellow' }, { name => 'total' } ],
output_template => '%s yellow health issue(s) found',
perfdatas => [
{ template => '%s', min => 0, max => 'total', label_extra_instance => 1 }
]
}
},
{ label => 'problems-red', nlabel => 'host.health.red.current.count', set => {
key_values => [ { name => 'red' }, { name => 'total' } ],
output_template => '%s red health issue(s) found',
perfdatas => [
{ template => '%s', min => 0, max => 'total', label_extra_instance => 1 }
]
}
}
];
$self->{maps_counters}->{global_summary} = [
{ label => 'global-summary', threshold => 0, set => {
key_values => [ { name => 'type' }, { name => 'name' }, { name => 'summary' } ],
closure_custom_output => $self->can('custom_summary_output'),
closure_custom_perfdata => sub { return 0; }
}
}
];
$self->{maps_counters}->{sensors_temp} = [
{ label => 'sensor-temperature', nlabel => 'host.sensor.temperature.celsius', set => {
key_values => [ { name => 'value' } ],
output_template => 'temperature: %s C',
perfdatas => [
{ template => '%s', unit => 'C', min => 0, label_extra_instance => 1 }
]
}
}
];
$self->{maps_counters}->{sensors_fan} = [
{ label => 'sensor-fan', nlabel => 'host.sensor.fan.speed.rpm', set => {
key_values => [ { name => 'value' } ],
output_template => 'fan speed: %s rpm',
perfdatas => [
{ template => '%s', unit => 'rpm', min => 0, label_extra_instance => 1 }
]
}
}
];
$self->{maps_counters}->{sensors_voltage} = [
{ label => 'sensor-voltage', nlabel => 'host.sensor.voltage.volt', set => {
key_values => [ { name => 'value' } ],
output_template => 'voltage: %s V',
perfdatas => [
{ template => '%s', unit => 'V', min => 0, label_extra_instance => 1 }
]
}
}
];
$self->{maps_counters}->{sensors_power} = [
{ label => 'sensor-power', nlabel => 'host.sensor.power.watt', set => {
key_values => [ { name => 'value' } ],
output_template => 'power: %s W',
perfdatas => [
{ template => '%s', unit => 'W', min => 0, label_extra_instance => 1 }
]
}
}
];
}
sub new { sub new {
my ($class, %options) = @_; my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options); my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class; bless $self, $class;
$options{options}->add_options(arguments => { $options{options}->add_options(arguments => {
@ -195,9 +245,10 @@ sub manage_selection {
global_summary => {}, global_summary => {},
global_problems => { global_problems => {
ok => 0, total_problems => 0, red => 0, yellow => 0, total => 0 ok => 0, total_problems => 0, red => 0, yellow => 0, total => 0
} },
sensors_temp => {}
}; };
my $i = 0; my $i = 0;
foreach (('memory_info', 'cpu_info', 'sensor_info', 'storage_info')) { foreach (('memory_info', 'cpu_info', 'sensor_info', 'storage_info')) {
if (defined($response->{data}->{$host_id}->{$_})) { if (defined($response->{data}->{$host_id}->{$_})) {
@ -221,6 +272,24 @@ sub manage_selection {
} }
} }
if (defined($response->{data}->{$host_id}->{sensor_info})) {
foreach my $entry (@{$response->{data}->{$host_id}->{sensor_info}}) {
next if ($entry->{current_reading} == 0);
$entry->{current_reading} *= 10 ** $entry->{power10};
$entry->{name} =~ s/\s---\s.+//;
if (lc($entry->{type}) eq 'temperature' && $entry->{unit} =~ /Degrees\s+C/i) {
$self->{host}->{$host_name}->{sensors_temp}->{ $entry->{name} } = { value => $entry->{current_reading} };
} elsif (lc($entry->{type}) eq 'fan' && $entry->{unit} =~ /rpm/i) {
$self->{host}->{$host_name}->{sensors_fan}->{ $entry->{name} } = { value => $entry->{current_reading} };
} elsif (lc($entry->{type}) eq 'voltage' && $entry->{unit} =~ /volts/i) {
$self->{host}->{$host_name}->{sensors_voltage}->{ $entry->{name} } = { value => $entry->{current_reading} };
} elsif (lc($entry->{type}) eq 'power' && $entry->{unit} =~ /watts/i) {
$self->{host}->{$host_name}->{sensors_power}->{ $entry->{name} } = { value => $entry->{current_reading} };
}
}
}
$self->{global}->{total_problems} += $self->{host}->{$host_name}->{global_problems}->{red} + $self->{host}->{$host_name}->{global_problems}->{yellow}; $self->{global}->{total_problems} += $self->{host}->{$host_name}->{global_problems}->{red} + $self->{host}->{$host_name}->{global_problems}->{yellow};
$self->{global}->{total} += $self->{host}->{$host_name}->{global_problems}->{total}; $self->{global}->{total} += $self->{host}->{$host_name}->{global_problems}->{total};
} }
@ -272,15 +341,11 @@ Can used special variables like: %{status}
Set critical threshold for status (Default: ''). Set critical threshold for status (Default: '').
Can used special variables like: %{status} Can used special variables like: %{status}
=item B<--warning-*> =item B<--warning-*> B<--critical-*>
Threshold warning. Thresholds.
Can be: 'total-problems', 'problems', 'problems-yellow', 'problems-red'. Can be: 'total-problems', 'problems', 'problems-yellow', 'problems-red',
'sensor-temperature', 'sensor-fan', 'sensor-voltage', 'sensor-power'.
=item B<--critical-*>
Threshold critical.
Can be: 'total-problems', 'problems', 'problems-yellow', 'problems-red'.
=back =back

View File

@ -0,0 +1,345 @@
#
# Copyright 2021 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 apps::vmware::connector::mode::licenses;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use centreon::plugins::misc;
use POSIX;
my $unitdiv = { s => 1, w => 604800, d => 86400, h => 3600, m => 60 };
my $unitdiv_long = { s => 'seconds', w => 'weeks', d => 'days', h => 'hours', m => 'minutes' };
sub custom_expires_perfdata {
my ($self, %options) = @_;
$self->{output}->perfdata_add(
nlabel => $self->{nlabel} . '.' . $unitdiv_long->{ $self->{instance_mode}->{option_results}->{unit} },
unit => $self->{instance_mode}->{option_results}->{unit},
instances => $self->{result_values}->{name},
value => floor($self->{result_values}->{expires_seconds} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }),
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}),
min => 0
);
}
sub custom_expires_threshold {
my ($self, %options) = @_;
return $self->{perfdata}->threshold_check(
value => floor($self->{result_values}->{expires_seconds} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }),
threshold => [
{ label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' },
{ label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' },
{ label => 'unknown-'. $self->{thlabel}, exit_litteral => 'unknown' }
]
);
}
sub custom_expires_output {
my ($self, %options) = @_;
my $msg;
if ($self->{result_values}->{expires_seconds} == 0) {
$msg = 'expired';
} else {
$msg = 'expires in ' . $self->{result_values}->{expires_human};
}
return $msg;
}
sub custom_usage_output {
my ($self, %options) = @_;
my $msg;
if ($self->{result_values}->{total} <= 0) {
$msg = sprintf('used: %s (unlimited)', $self->{result_values}->{used});
} else {
$msg = sprintf(
"total: %s used: %s (%.2f%%) free: %s (%.2f%%)",
$self->{result_values}->{total},
$self->{result_values}->{used}, $self->{result_values}->{prct_used},
$self->{result_values}->{free}, $self->{result_values}->{prct_free}
);
}
return $msg;
}
sub custom_usage_calc {
my ($self, %options) = @_;
$self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'};
$self->{result_values}->{edition} = $options{new_datas}->{$self->{instance} . '_edition'};
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'};
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'};
if ($self->{result_values}->{total} == 0) {
return -10 if ($options{extra_options}->{label} ne 'usage');
return 0;
}
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
$self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used};
$self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used};
return 0;
}
sub prefix_license_output {
my ($self, %options) = @_;
return sprintf(
"License '%s' [edition: %s] ",
$options{instance},
$options{instance_value}->{edition}
);
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'global', type => 0, skipped_code => { -10 => 1 } },
{ name => 'licenses', type => 1, cb_prefix_output => 'prefix_license_output', message_multiple => 'All licenses are ok', skipped_code => { -10 => 1 } }
];
$self->{maps_counters}->{global} = [
{ label => 'total-licenses', nlabel => 'licenses.total.count', set => {
key_values => [ { name => 'total' } ],
output_template => 'Number of licenses: %s',
perfdatas => [
{ template => '%s', min => 0 }
]
}
}
];
$self->{maps_counters}->{licenses} = [
{ label => 'usage', nlabel => 'license.usage.count', set => {
key_values => [
{ name => 'edition' }, { name => 'name' }, { name => 'used' }, { name => 'total' }
],
closure_custom_calc_extra_options => { label => 'usage' },
closure_custom_calc => $self->can('custom_usage_calc'),
closure_custom_output => $self->can('custom_usage_output'),
closure_custom_threshold_check => sub {
my ($self, %options) = @_;
return $self->{perfdata}->threshold_check(
value => $self->{result_values}->{used}, threshold => [
{ label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' },
{ label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' }
]
);
},
closure_custom_perfdata => sub {
my ($self, %options) = @_;
$self->{output}->perfdata_add(
nlabel => $self->{nlabel},
instances => $self->{result_values}->{name},
value => $self->{result_values}->{used},
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}),
min => 0,
max => $self->{result_values}->{total} > 0 ? $self->{result_values}->{total} : undef
);
}
}
},
{ label => 'usage-free', nlabel => 'license.free.count', display_ok => 0, set => {
key_values => [
{ name => 'edition' }, { name => 'name' }, { name => 'used' }, { name => 'total' }
],
closure_custom_calc_extra_options => { label => 'free' },
closure_custom_calc => $self->can('custom_usage_calc'),
closure_custom_output => $self->can('custom_usage_output'),
closure_custom_threshold_check => sub {
my ($self, %options) = @_;
return $self->{perfdata}->threshold_check(
value => $self->{result_values}->{free}, threshold => [
{ label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' },
{ label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' }
]
);
},
closure_custom_perfdata => sub {
my ($self, %options) = @_;
$self->{output}->perfdata_add(
nlabel => $self->{nlabel},
instances => $self->{result_values}->{name},
value => $self->{result_values}->{free},
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}),
min => 0,
max => $self->{result_values}->{total}
);
}
}
},
{ label => 'usage-prct', nlabel => 'license.usage.percentage', display_ok => 0, set => {
key_values => [
{ name => 'edition' }, { name => 'name' }, { name => 'used' }, { name => 'total' }
],
closure_custom_calc_extra_options => { label => 'prct' },
closure_custom_calc => $self->can('custom_usage_calc'),
closure_custom_output => $self->can('custom_usage_output'),
closure_custom_threshold_check => sub {
my ($self, %options) = @_;
return $self->{perfdata}->threshold_check(
value => $self->{result_values}->{prct_used}, threshold => [
{ label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' },
{ label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' }
]
);
},
closure_custom_perfdata => sub {
my ($self, %options) = @_;
$self->{output}->perfdata_add(
nlabel => $self->{nlabel},
unit => '%',
instances => $self->{result_values}->{name},
value => $self->{result_values}->{prct_used},
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}),
min => 0, max => 100
);
}
}
},
{ label => 'expires', nlabel => 'license.expires', set => {
key_values => [ { name => 'expires_seconds' }, { name => 'expires_human' }, { name => 'name' } ],
closure_custom_output => $self->can('custom_expires_output'),
closure_custom_perfdata => $self->can('custom_expires_perfdata'),
closure_custom_threshold_check => $self->can('custom_expires_threshold')
}
}
];
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'filter-name:s' => { name => 'filter_name' },
'exclude-name:s' => { name => 'exclude_name' },
'filter-edition:s' => { name => 'filter_edition' },
'exclude-edition:s' => { name => 'exclude_edition' },
'unit:s' => { name => 'unit', default => 'd' }
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
if ($self->{option_results}->{unit} eq '' || !defined($unitdiv->{$self->{option_results}->{unit}})) {
$self->{option_results}->{unit} = 'd';
}
}
sub manage_selection {
my ($self, %options) = @_;
my $response = $options{custom}->execute(
params => $self->{option_results},
command => 'licenses'
);
$self->{global} = { total => 0 };
$self->{licenses} = {};
foreach my $name (keys %{$response->{data}}) {
next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$name !~ /$self->{option_results}->{filter_name}/);
next if (defined($self->{option_results}->{exclude_name}) && $self->{option_results}->{exclude_name} ne '' &&
$name =~ /$self->{option_results}->{exclude_name}/);
next if (defined($self->{option_results}->{filter_edition}) && $self->{option_results}->{filter_edition} ne '' &&
$response->{data}->{$name}->{edition} !~ /$self->{option_results}->{filter_edition}/);
next if (defined($self->{option_results}->{exclude_edition}) && $self->{option_results}->{exclude_edition} ne '' &&
$response->{data}->{$name}->{edition} =~ /$self->{option_results}->{exclude_edition}/);
next if (!defined($response->{data}->{$name}->{used}) && !defined($response->{data}->{$name}->{expiration_minutes}));
$self->{licenses}->{$name} = {
name => $name,
edition => $response->{data}->{$name}->{edition},
total => $response->{data}->{$name}->{total},
used => $response->{data}->{$name}->{used}
};
if (defined($response->{data}->{$name}->{expiration_minutes})) {
$self->{licenses}->{$name}->{expires_seconds} = $response->{data}->{$name}->{expiration_minutes} * 60;
$self->{licenses}->{$name}->{expires_human} = centreon::plugins::misc::change_seconds(
value => $self->{licenses}->{$name}->{expires_seconds}
);
}
$self->{global}->{total}++;
}
}
1;
__END__
=head1 MODE
Check licenses.
=over 8
=item B<--filter-name>
Filter licenses by name (can be a regexp).
=item B<--exclude-name>
Exclude licenses by name (can be a regexp).
=item B<--filter-edition>
Filter licenses by edition name (can be a regexp).
=item B<--exclude-edition>
Exclude licenses by edition name (can be a regexp).
=item B<--unit>
Select the unit for expires threshold. May be 's' for seconds, 'm' for minutes,
'h' for hours, 'd' for days, 'w' for weeks. Default is days.
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'total-licenses', 'usage', 'usage-free', 'usage-prct', 'expires'.
=back
=cut

View File

@ -58,7 +58,7 @@ sub custom_traffic_output {
my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{traffic}, network => 1); my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{traffic}, network => 1);
return sprintf( return sprintf(
"traffic %s : %s/s (%.2f %%)", "traffic %s: %s/s (%.2f %%)",
$self->{result_values}->{label_ref}, $value . $unit, $self->{result_values}->{traffic_prct} $self->{result_values}->{label_ref}, $value . $unit, $self->{result_values}->{traffic_prct}
); );
} }
@ -79,7 +79,7 @@ sub custom_dropped_output {
my ($self, %options) = @_; my ($self, %options) = @_;
return sprintf( return sprintf(
'packets %s dropped : %.2f %% (%d/%d packets)', 'packets %s dropped: %.2f %% (%d/%d packets)',
$self->{result_values}->{label_ref}, $self->{result_values}->{label_ref},
$self->{result_values}->{dropped_prct}, $self->{result_values}->{dropped_prct},
$self->{result_values}->{dropped}, $self->{result_values}->{packets} $self->{result_values}->{dropped}, $self->{result_values}->{packets}
@ -131,7 +131,7 @@ sub set_counters {
$self->{maps_counters}->{global_host} = [ $self->{maps_counters}->{global_host} = [
{ label => 'host-traffic-in', nlabel => 'host.traffic.in.bitsperseconds', set => { { label => 'host-traffic-in', nlabel => 'host.traffic.in.bitsperseconds', set => {
key_values => [ { name => 'traffic_in' } ], key_values => [ { name => 'traffic_in' } ],
output_template => 'host traffic in : %s %s/s', output_template => 'host traffic in: %s %s/s',
output_change_bytes => 2, output_change_bytes => 2,
perfdatas => [ perfdatas => [
{ label => 'host_traffic_in', template => '%s', { label => 'host_traffic_in', template => '%s',
@ -141,7 +141,7 @@ sub set_counters {
}, },
{ label => 'host-traffic-out', nlabel => 'host.traffic.out.bitsperseconds', set => { { label => 'host-traffic-out', nlabel => 'host.traffic.out.bitsperseconds', set => {
key_values => [ { name => 'traffic_out' } ], key_values => [ { name => 'traffic_out' } ],
output_template => 'host traffic out : %s %s/s', output_template => 'host traffic out: %s %s/s',
output_change_bytes => 2, output_change_bytes => 2,
perfdatas => [ perfdatas => [
{ label => 'host_traffic_out', template => '%s', { label => 'host_traffic_out', template => '%s',
@ -154,17 +154,17 @@ sub set_counters {
$self->{maps_counters}->{vswitch} = [ $self->{maps_counters}->{vswitch} = [
{ label => 'vswitch-traffic-in', nlabel => 'host.vswitch.traffic.in.bitsperseconds', set => { { label => 'vswitch-traffic-in', nlabel => 'host.vswitch.traffic.in.bitsperseconds', set => {
key_values => [ { name => 'traffic_in' } ], key_values => [ { name => 'traffic_in' } ],
output_template => 'traffic in : %s %s/s', output_template => 'traffic in: %s %s/s',
output_change_bytes => 2, output_change_bytes => 2,
perfdatas => [ perfdatas => [
{ label => 'vswitch_traffic_in', template => '%s', { label => 'vswitch_traffic_in', template => '%s',
unit => 'b/s', min => 0, label_extra_instance => 1 }, unit => 'b/s', min => 0, label_extra_instance => 1 }
], ]
} }
}, },
{ label => 'vswitch-traffic-out', nlabel => 'host.vswitch.traffic.out.bitsperseconds', set => { { label => 'vswitch-traffic-out', nlabel => 'host.vswitch.traffic.out.bitsperseconds', set => {
key_values => [ { name => 'traffic_out' } ], key_values => [ { name => 'traffic_out' } ],
output_template => 'traffic out : %s %s/s', output_template => 'traffic out: %s %s/s',
output_change_bytes => 2, output_change_bytes => 2,
perfdatas => [ perfdatas => [
{ label => 'vswitch_traffic_out', template => '%s', { label => 'vswitch_traffic_out', template => '%s',
@ -262,12 +262,13 @@ sub new {
bless $self, $class; bless $self, $class;
$options{options}->add_options(arguments => { $options{options}->add_options(arguments => {
'esx-hostname:s' => { name => 'esx_hostname' }, 'esx-hostname:s' => { name => 'esx_hostname' },
'nic-name:s' => { name => 'nic_name' }, 'nic-name:s' => { name => 'nic_name' },
'filter' => { name => 'filter' }, 'filter' => { name => 'filter' },
'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' },
'scope-cluster:s' => { name => 'scope_cluster' }, 'scope-cluster:s' => { name => 'scope_cluster' },
'no-proxyswitch' => { name => 'no_proxyswitch' } 'no-proxyswitch' => { name => 'no_proxyswitch' },
'filter-vswitch-name:s' => { name => 'filter_vswitch_name' }
}); });
return $self; return $self;
@ -284,21 +285,36 @@ sub manage_selection {
foreach my $host_id (keys %{$response->{data}}) { foreach my $host_id (keys %{$response->{data}}) {
my $host_name = $response->{data}->{$host_id}->{name}; my $host_name = $response->{data}->{$host_id}->{name};
$self->{host}->{$host_name} = { display => $host_name, $self->{host}->{$host_name} = {
display => $host_name,
global => { global => {
state => $response->{data}->{$host_id}->{state}, state => $response->{data}->{$host_id}->{state}
}, },
global_host => { global_host => {
traffic_in => 0, traffic_in => 0,
traffic_out => 0 traffic_out => 0
} }
}; };
foreach my $pnic_name (sort keys %{$response->{data}->{$host_id}->{pnic}}) { foreach my $pnic_name (sort keys %{$response->{data}->{$host_id}->{pnic}}) {
$self->{host}->{$host_name}->{pnic} = {} if (!defined($self->{host}->{$host_name}->{pnic})); $self->{host}->{$host_name}->{pnic} = {} if (!defined($self->{host}->{$host_name}->{pnic}));
next if (defined($self->{option_results}->{nic_name}) && $self->{option_results}->{nic_name} ne '' && next if (defined($self->{option_results}->{nic_name}) && $self->{option_results}->{nic_name} ne '' &&
$pnic_name !~ /$self->{option_results}->{nic_name}/); $pnic_name !~ /$self->{option_results}->{nic_name}/);
my $filtered = 1;
if (defined($self->{option_results}->{filter_vswitch_name}) && $self->{option_results}->{filter_vswitch_name} ne '') {
$filtered = 0;
foreach my $vswitch_name (keys %{$response->{data}->{$host_id}->{vswitch}}) {
next if (!defined($response->{data}->{$host_id}->{vswitch}->{$vswitch_name}->{pnic}));
next if ($vswitch_name !~ /$self->{option_results}->{filter_vswitch_name}/);
foreach (@{$response->{data}->{$host_id}->{vswitch}->{$vswitch_name}->{pnic}}) {
$filtered = 1 if ($_ eq $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{key});
}
}
}
next if ($filtered == 0);
$self->{host}->{$host_name}->{pnic}->{$pnic_name} = { $self->{host}->{$host_name}->{pnic}->{$pnic_name} = {
display => $pnic_name, display => $pnic_name,
status => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{status} , status => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{status} ,
@ -310,9 +326,9 @@ sub manage_selection {
dropped_in => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.droppedRx.summation'}, dropped_in => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.droppedRx.summation'},
dropped_out => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.droppedTx.summation'} dropped_out => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.droppedTx.summation'}
}; };
next if (!defined($response->{data}->{$host_id}->{pnic}->{$pnic_name}->{speed})); next if (!defined($response->{data}->{$host_id}->{pnic}->{$pnic_name}->{speed}));
foreach my $vswitch_name (keys %{$response->{data}->{$host_id}->{vswitch}}) { foreach my $vswitch_name (keys %{$response->{data}->{$host_id}->{vswitch}}) {
next if (!defined($response->{data}->{$host_id}->{vswitch}->{$vswitch_name}->{pnic})); next if (!defined($response->{data}->{$host_id}->{vswitch}->{$vswitch_name}->{pnic}));
foreach (@{$response->{data}->{$host_id}->{vswitch}->{$vswitch_name}->{pnic}}) { foreach (@{$response->{data}->{$host_id}->{vswitch}->{$vswitch_name}->{pnic}}) {
@ -326,7 +342,7 @@ sub manage_selection {
} }
} }
} }
$self->{host}->{$host_name}->{global_host}->{traffic_in} += $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.received.average'} $self->{host}->{$host_name}->{global_host}->{traffic_in} += $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.received.average'}
if (defined($response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.received.average'})); if (defined($response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.received.average'}));
$self->{host}->{$host_name}->{global_host}->{traffic_out} += $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.transmitted.average'} $self->{host}->{$host_name}->{global_host}->{traffic_out} += $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.transmitted.average'}
@ -367,6 +383,11 @@ Search in following cluster(s) (can be a regexp).
ESX nic to check. ESX nic to check.
If not set, we check all nics. If not set, we check all nics.
=item B<--filter-vswitch-name>
Filter vswitch by name.
It monitors only ESX nic that belongs to the filtered vswitches.
=item B<--unknown-status> =item B<--unknown-status>
Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Set warning threshold for status (Default: '%{status} !~ /^connected$/i').

View File

@ -43,10 +43,11 @@ sub new {
'display-description' => { name => 'display_description' }, 'display-description' => { name => 'display_description' },
'check-consolidation' => { name => 'check_consolidation' }, 'check-consolidation' => { name => 'check_consolidation' },
'nopoweredon-skip' => { name => 'nopoweredon_skip' }, 'nopoweredon-skip' => { name => 'nopoweredon_skip' },
'empty-continue' => { name => 'empty_continue' },
'warning:s' => { name => 'warning' }, 'warning:s' => { name => 'warning' },
'critical:s' => { name => 'critical' }, 'critical:s' => { name => 'critical' },
'disconnect-status:s' => { name => 'disconnect_status', default => 'unknown' }, 'disconnect-status:s' => { name => 'disconnect_status', default => 'unknown' },
'unit:s' => { name => 'unit', default => 's' }, 'unit:s' => { name => 'unit', default => 's' }
}); });
return $self; return $self;
@ -80,9 +81,11 @@ sub check_options {
sub run { sub run {
my ($self, %options) = @_; my ($self, %options) = @_;
my $response = $options{custom}->execute(params => $self->{option_results}, my $response = $options{custom}->execute(
command => 'snapshotvm'); params => $self->{option_results},
command => 'snapshotvm'
);
my $multiple = 0; my $multiple = 0;
my %vm_consolidate = (); my %vm_consolidate = ();
my %vm_errors = (warning => {}, critical => {}); my %vm_errors = (warning => {}, critical => {});
@ -90,28 +93,34 @@ sub run {
$multiple = 1; $multiple = 1;
} }
if ($multiple == 1) { if ($multiple == 1) {
$self->{output}->output_add(severity => 'OK', $self->{output}->output_add(
short_msg => sprintf("All snapshots are ok")); severity => 'OK',
short_msg => sprintf("All snapshots are ok")
);
} else { } else {
$self->{output}->output_add(severity => 'OK', $self->{output}->output_add(
short_msg => sprintf("Snapshot(s) OK")); severity => 'OK',
short_msg => sprintf("Snapshot(s) OK")
);
} }
foreach my $vm_id (sort keys %{$response->{data}}) { foreach my $vm_id (sort keys %{$response->{data}}) {
my $vm_name = $response->{data}->{$vm_id}->{name}; my $vm_name = $response->{data}->{$vm_id}->{name};
if ($options{custom}->entity_is_connected(state => $response->{data}->{$vm_id}->{connection_state}) == 0) { if ($options{custom}->entity_is_connected(state => $response->{data}->{$vm_id}->{connection_state}) == 0) {
my $output = "VM '" . $vm_name . "' not connected. Current Connection State: '$response->{data}->{$vm_id}->{connection_state}'."; my $output = "VM '" . $vm_name . "' not connected. Current Connection State: '$response->{data}->{$vm_id}->{connection_state}'.";
if ($multiple == 0 || if ($multiple == 0 ||
!$self->{output}->is_status(value => $self->{option_results}->{disconnect_status}, compare => 'ok', litteral => 1)) { !$self->{output}->is_status(value => $self->{option_results}->{disconnect_status}, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(severity => $self->{option_results}->{disconnect_status}, $self->{output}->output_add(
short_msg => $output); severity => $self->{option_results}->{disconnect_status},
short_msg => $output
);
} }
next; next;
} }
next if (defined($self->{option_results}->{nopoweredon_skip}) && next if (defined($self->{option_results}->{nopoweredon_skip}) &&
$options{custom}->vm_is_running(power => $response->{data}->{$vm_id}->{power_state}) == 0); $options{custom}->vm_is_running(power => $response->{data}->{$vm_id}->{power_state}) == 0);
if (defined($self->{check_consolidation}) && defined($response->{data}->{$vm_id}->{consolidation_needed}) && $response->{data}->{$vm_id}->{consolidation_needed} == 1) { if (defined($self->{check_consolidation}) && defined($response->{data}->{$vm_id}->{consolidation_needed}) && $response->{data}->{$vm_id}->{consolidation_needed} == 1) {
$vm_consolidate{$response->{data}->{$vm_id}->{name}} = 1; $vm_consolidate{$response->{data}->{$vm_id}->{name}} = 1;
} }
@ -119,15 +128,17 @@ sub run {
foreach (@{$response->{data}->{$vm_id}->{snapshosts}}) { foreach (@{$response->{data}->{$vm_id}->{snapshosts}}) {
my $create_time = Date::Parse::str2time($_->{create_time}); my $create_time = Date::Parse::str2time($_->{create_time});
if (!defined($create_time)) { if (!defined($create_time)) {
$self->{output}->output_add(severity => 'UNKNOWN', $self->{output}->output_add(
short_msg => "Can't Parse date '" . $_->{create_time} . "' for vm '" . $vm_name . "'"); severity => 'UNKNOWN',
short_msg => "Can't Parse date '" . $_->{create_time} . "' for vm '" . $vm_name . "'"
);
next; next;
} }
my $diff_time = time() - $create_time; my $diff_time = time() - $create_time;
my $days = int($diff_time / 60 / 60 / 24); my $days = int($diff_time / 60 / 60 / 24);
my $exit = $self->{perfdata}->threshold_check(value => ($diff_time / $unitdiv->{$self->{option_results}->{unit}}->[1]), threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); my $exit = $self->{perfdata}->threshold_check(value => ($diff_time / $unitdiv->{$self->{option_results}->{unit}}->[1]), threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]);
my $prefix_msg = "'$vm_name'"; my $prefix_msg = "'$vm_name'";
if (defined($self->{display_description}) && defined($response->{data}->{$vm_id}->{'config.annotation'}) && if (defined($self->{display_description}) && defined($response->{data}->{$vm_id}->{'config.annotation'}) &&
$response->{data}->{$vm_id}->{'config.annotation'} ne '') { $response->{data}->{$vm_id}->{'config.annotation'} ne '') {
@ -187,7 +198,7 @@ sub run {
) )
); );
} }
$self->{output}->display(); $self->{output}->display();
$self->{output}->exit(); $self->{output}->exit();
} }
@ -247,6 +258,10 @@ Status if VM disconnected (default: 'unknown').
Skip check if VM is not poweredOn. Skip check if VM is not poweredOn.
=item B<--empty-continue>
Ask to the connector that an empty response is ok.
=item B<--unit> =item B<--unit>
Select the unit for performance data and thresholds. May be 's' for seconds, 'm' for minutes, Select the unit for performance data and thresholds. May be 's' for seconds, 'm' for minutes,

View File

@ -97,7 +97,7 @@ sub manage_selection {
foreach my $cluster_id (keys %{$response->{data}}) { foreach my $cluster_id (keys %{$response->{data}}) {
my $cluster_name = $response->{data}->{$cluster_id}->{name}; my $cluster_name = $response->{data}->{$cluster_id}->{name};
$self->{cluster}->{$cluster_name} = { $self->{cluster}->{$cluster_name} = {
display => $cluster_name, display => $cluster_name,
overall_status => $response->{data}->{$cluster_id}->{overall_status}, overall_status => $response->{data}->{$cluster_id}->{overall_status},
vsan_status => defined($response->{data}->{$cluster_id}->{vsan_cluster_status}) ? $response->{data}->{$cluster_id}->{vsan_cluster_status} : '', vsan_status => defined($response->{data}->{$cluster_id}->{vsan_cluster_status}) ? $response->{data}->{$cluster_id}->{vsan_cluster_status} : '',
ha_enabled => defined($response->{data}->{$cluster_id}->{ha_enabled}) ? $response->{data}->{$cluster_id}->{ha_enabled} : '', ha_enabled => defined($response->{data}->{$cluster_id}->{ha_enabled}) ? $response->{data}->{$cluster_id}->{ha_enabled} : '',

View File

@ -0,0 +1,414 @@
#
# Copyright 2021 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 apps::vmware::connector::mode::storagehost;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
sub custom_status_output {
my ($self, %options) = @_;
return 'status ' . $self->{result_values}->{status} . ', maintenance mode is ' . $self->{result_values}->{maintenance};
}
sub custom_status_calc {
my ($self, %options) = @_;
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'};
$self->{result_values}->{maintenance} = $options{new_datas}->{$self->{instance} . '_maintenance'};
return 0;
}
sub custom_adapter_output {
my ($self, %options) = @_;
return sprintf(
'status: %s',
$self->{result_values}->{status}
);
}
sub prefix_host_output {
my ($self, %options) = @_;
return "Host '" . $options{instance} . "' : ";
}
sub host_long_output {
my ($self, %options) = @_;
return "checking host '" . $options{instance} . "'";
}
sub prefix_adapters_output {
my ($self, %options) = @_;
return 'adapters ';
}
sub prefix_adapter_output {
my ($self, %options) = @_;
return "adapter '" . $options{instance_value}->{name} . "' ";
}
sub prefix_luns_output {
my ($self, %options) = @_;
return 'luns ';
}
sub prefix_lun_output {
my ($self, %options) = @_;
return "lun '" . $options{instance_value}->{name} . "' ";
}
sub prefix_paths_output {
my ($self, %options) = @_;
return 'paths ';
}
sub prefix_path_output {
my ($self, %options) = @_;
return "path '" . $options{instance_value}->{name} . "' ";
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'host', type => 3, cb_prefix_output => 'prefix_host_output', cb_long_output => 'host_long_output', indent_long_output => ' ', message_multiple => 'All ESX hosts are ok',
group => [
{ name => 'global', type => 0, skipped_code => { -10 => 1 } },
{ name => 'adapters_global', type => 0, cb_prefix_output => 'prefix_adapters_output', skipped_code => { -10 => 1 } },
{ name => 'luns_global', type => 0, cb_prefix_output => 'prefix_luns_output', skipped_code => { -10 => 1 } },
{ name => 'paths_global', type => 0, cb_prefix_output => 'prefix_paths_output', skipped_code => { -10 => 1 } },
{ name => 'adapters', type => 1, display_long => 1, cb_prefix_output => 'prefix_adapter_output', message_multiple => 'All adapters are ok', skipped_code => { -10 => 1 } },
{ name => 'luns', type => 1, display_long => 1, cb_prefix_output => 'prefix_lun_output', message_multiple => 'All luns are ok', skipped_code => { -10 => 1 } },
{ name => 'paths', type => 1, display_long => 1, cb_prefix_output => 'prefix_path_output', message_multiple => 'All paths are ok', skipped_code => { -10 => 1 } }
]
}
];
$self->{maps_counters}->{global} = [
{
label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i && %{maintenance} =~ /false/i',
set => {
key_values => [ { name => 'state' }, { name => 'maintenance' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold_ng
}
}
];
$self->{maps_counters}->{adapters_global} = [];
foreach ('total', 'online', 'offline', 'fault', 'unknown') {
push @{$self->{maps_counters}->{adapters_global}}, {
label => 'adapters-' . $_, nlabel => 'host.adapters.' . $_ . '.count', set => {
key_values => [ { name => $_ } ],
output_template => $_ . ': %s',
perfdatas => [
{ template => '%s', min => 0, label_extra_instance => 1 }
]
}
};
}
$self->{maps_counters}->{luns_global} = [];
foreach ('total', 'ok', 'error', 'off', 'unknown', 'quiesced', 'degraded') {
push @{$self->{maps_counters}->{luns_global}}, {
label => 'luns-' . $_, nlabel => 'host.luns.' . $_ . '.count', set => {
key_values => [ { name => $_ } ],
output_template => $_ . ': %s',
perfdatas => [
{ template => '%s', min => 0, label_extra_instance => 1 }
]
}
};
}
$self->{maps_counters}->{paths_global} = [];
foreach ('total', 'active', 'disabled', 'standby', 'dead', 'unknown') {
push @{$self->{maps_counters}->{paths_global}}, {
label => 'paths-' . $_, nlabel => 'host.paths.' . $_ . '.count', set => {
key_values => [ { name => $_ } ],
output_template => $_ . ': %s',
perfdatas => [
{ template => '%s', min => 0, label_extra_instance => 1 }
]
}
};
}
$self->{maps_counters}->{adapters} = [
{
label => 'adapter-status', type => 2, critical_default => '%{status} =~ /fault/',
set => {
key_values => [ { name => 'name' }, { name => 'status' }, { name => 'host' } ],
closure_custom_output => $self->can('custom_adapter_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold_ng
}
}
];
$self->{maps_counters}->{luns} = [
{
label => 'lun-status',
type => 2,
warning_default => '%{status} =~ /degraded|quiesced/',
critical_default => '%{status} =~ /lostcommunication|error/',
set => {
key_values => [ { name => 'name' }, { name => 'status' }, { name => 'host' } ],
closure_custom_output => $self->can('custom_adapter_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold_ng
}
}
];
$self->{maps_counters}->{paths} = [
{
label => 'path-status',
type => 2,
critical_default => '%{status} =~ /dead/',
set => {
key_values => [ { name => 'name' }, { name => 'status' }, { name => 'host' } ],
closure_custom_output => $self->can('custom_adapter_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold_ng
}
}
];
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'esx-hostname:s' => { name => 'esx_hostname' },
'filter' => { name => 'filter' },
'scope-datacenter:s' => { name => 'scope_datacenter' },
'scope-cluster:s' => { name => 'scope_cluster' },
'filter-adapter-name:s' => { name => 'filter_adapter_name' },
'filter-lun-name:s' => { name => 'filter_lun_name' },
'filter-path-name:s' => { name => 'filter_path_name' }
});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
$self->{host} = {};
my $response = $options{custom}->execute(
params => $self->{option_results},
command => 'storagehost'
);
foreach my $host_id (keys %{$response->{data}}) {
my $host_name = $response->{data}->{$host_id}->{name};
$self->{host}->{$host_name} = {
global => {
state => $response->{data}->{$host_id}->{state},
maintenance => $response->{data}->{$host_id}->{inMaintenanceMode}
}
};
if (defined($response->{data}->{$host_id}->{adapters})) {
$self->{host}->{$host_name}->{adapters} = {};
$self->{host}->{$host_name}->{adapters_global} = {
online => 0, offline => 0, fault => 0, unknown => 0, total => 0
};
foreach (@{$response->{data}->{$host_id}->{adapters}}) {
next if (defined($self->{option_results}->{filter_adapter_name}) && $self->{option_results}->{filter_adapter_name} ne '' &&
$_->{name} !~ /$self->{option_results}->{filter_adapter_name}/);
$self->{host}->{$host_name}->{adapters_global}->{total}++;
if (defined($self->{host}->{$host_name}->{adapters_global}->{ $_->{status} })) {
$self->{host}->{$host_name}->{adapters_global}->{ $_->{status} }++;
} else {
$self->{host}->{$host_name}->{adapters_global}->{unknown}++;
}
$self->{host}->{$host_name}->{adapters}->{ $_->{name} } = {
name => $_->{name},
host => $host_name,
status => $_->{status}
};
}
}
if (defined($response->{data}->{$host_id}->{luns})) {
$self->{host}->{$host_name}->{luns} = {};
$self->{host}->{$host_name}->{luns_global} = {
ok => 0, error => 0, off => 0, unknown => 0, quiesced => 0, degraded => 0, total => 0
};
foreach (@{$response->{data}->{$host_id}->{luns}}) {
next if (defined($self->{option_results}->{filter_lun_name}) && $self->{option_results}->{filter_lun_name} ne '' &&
$_->{name} !~ /$self->{option_results}->{filter_lun_name}/);
$self->{host}->{$host_name}->{luns_global}->{total}++;
foreach my $state (@{$_->{operational_states}}) {
if (defined($self->{host}->{$host_name}->{luns_global}->{$state})) {
$self->{host}->{$host_name}->{luns_global}->{$state}++;
} else {
$self->{host}->{$host_name}->{luns_global}->{unknown}++;
}
}
$self->{host}->{$host_name}->{luns}->{ $_->{name} } = {
name => $_->{name},
host => $host_name,
status => join(',', @{$_->{operational_states}})
};
}
}
if (defined($response->{data}->{$host_id}->{paths})) {
$self->{host}->{$host_name}->{paths} = {};
$self->{host}->{$host_name}->{paths_global} = {
active => 0, disabled => 0, standby => 0, dead => 0, unknown => 0
};
foreach (@{$response->{data}->{$host_id}->{paths}}) {
next if (defined($self->{option_results}->{filter_path_name}) && $self->{option_results}->{filter_path_name} ne '' &&
$_->{name} !~ /$self->{option_results}->{filter_path_name}/);
$self->{host}->{$host_name}->{paths_global}->{total}++;
if (defined($self->{host}->{$host_name}->{paths_global}->{ $_->{state} })) {
$self->{host}->{$host_name}->{paths_global}->{ $_->{state} }++;
} else {
$self->{host}->{$host_name}->{paths_global}->{unknown}++;
}
$self->{host}->{$host_name}->{paths}->{ $_->{name} } = {
name => $_->{name},
host => $host_name,
status => $_->{state}
};
}
}
}
}
1;
__END__
=head1 MODE
Check ESX storage infos.
=over 8
=item B<--esx-hostname>
ESX hostname to check.
If not set, we check all ESX.
=item B<--filter>
ESX hostname is a regexp.
=item B<--scope-datacenter>
Search in following datacenter(s) (can be a regexp).
=item B<--scope-cluster>
Search in following cluster(s) (can be a regexp).
=item B<--filter-adapter-name>
Filter adapters by name (can be a regexp).
=item B<--filter-lun-name>
Filter luns by name (can be a regexp).
=item B<--filter-path-name>
Filter paths by name (can be a regexp).
=item B<--unknown-status>
Set warning threshold for status (Default: '%{status} !~ /^connected$/i && %{maintenance} =~ /false/i').
Can used special variables like: %{status}, %{maintenance}
=item B<--warning-status>
Set warning threshold for status.
Can used special variables like: %{status}, %{maintenance}
=item B<--critical-status>
Set critical threshold for status.
Can used special variables like: %{status}, %{maintenance}
=item B<--warning-adapter-status>
Set warning threshold for adapter status.
Can used special variables like: %{name}, %{host}, %{status}
=item B<--critical-adapter-status>
Set critical threshold for adapter status (Default: '%{status} =~ /fault/').
Can used special variables like: %{name}, %{host}, %{status}
=item B<--warning-lun-status>
Set warning threshold for lun status (Default: '%{status} =~ /degraded|quiesced/').
Can used special variables like: %{name}, %{host}, %{status}
=item B<--critical-lun-status>
Set critical threshold for lun status (Default: '%{status} =~ /lostcommunication|error/').
Can used special variables like: %{name}, %{host}, %{status}
=item B<--warning-path-status>
Set warning threshold for path status.
Can used special variables like: %{name}, %{host}, %{status}
=item B<--critical-path-status>
Set critical threshold for path status (Default: '%{status} =~ /dead/').
Can used special variables like: %{name}, %{host}, %{status}
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'adapters-total', 'adapters-online', 'adapters-offline', 'adapters-fault', 'adapters-unknown',
=back
=cut

View File

@ -31,20 +31,21 @@ sub new {
bless $self, $class; bless $self, $class;
$options{options}->add_options(arguments => { $options{options}->add_options(arguments => {
"vm-hostname:s" => { name => 'vm_hostname' }, 'vm-hostname:s' => { name => 'vm_hostname' },
"filter" => { name => 'filter' }, 'filter' => { name => 'filter' },
"scope-datacenter:s" => { name => 'scope_datacenter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' },
"scope-cluster:s" => { name => 'scope_cluster' }, 'scope-cluster:s' => { name => 'scope_cluster' },
"scope-host:s" => { name => 'scope_host' }, 'scope-host:s' => { name => 'scope_host' },
"filter-description:s" => { name => 'filter_description' }, 'filter-description:s' => { name => 'filter_description' },
"filter-os:s" => { name => 'filter_os' }, 'filter-os:s' => { name => 'filter_os' },
"filter-uuid:s" => { name => 'filter_uuid' }, 'filter-uuid:s' => { name => 'filter_uuid' },
"display-description" => { name => 'display_description' }, 'display-description' => { name => 'display_description' },
"disconnect-status:s" => { name => 'disconnect_status', default => 'unknown' }, 'disconnect-status:s' => { name => 'disconnect_status', default => 'unknown' },
"tools-notinstalled-status:s" => { name => 'tools_notinstalled_status', default => 'critical' }, 'tools-notinstalled-status:s' => { name => 'tools_notinstalled_status', default => 'critical' },
"tools-notrunning-status:s" => { name => 'tools_notrunning_status', default => 'critical' }, 'tools-notrunning-status:s' => { name => 'tools_notrunning_status', default => 'critical' },
"tools-notup2date-status:s" => { name => 'tools_notupd2date_status', default => 'warning' }, 'tools-notup2date-status:s' => { name => 'tools_notupd2date_status', default => 'warning' },
"nopoweredon-skip" => { name => 'nopoweredon_skip' }, 'nopoweredon-skip' => { name => 'nopoweredon_skip' },
'empty-continue' => { name => 'empty_continue' }
}); });
return $self; return $self;
@ -88,21 +89,27 @@ sub display_verbose {
sub run { sub run {
my ($self, %options) = @_; my ($self, %options) = @_;
my $response = $options{custom}->execute(params => $self->{option_results}, my $response = $options{custom}->execute(
command => 'toolsvm'); params => $self->{option_results},
command => 'toolsvm'
);
my $multiple = 0; my $multiple = 0;
if (scalar(keys %{$response->{data}}) > 1) { if (scalar(keys %{$response->{data}}) > 1) {
$multiple = 1; $multiple = 1;
} }
if ($multiple == 1) { if ($multiple == 1) {
$self->{output}->output_add(severity => 'OK', $self->{output}->output_add(
short_msg => 'All VMTools are OK'); severity => 'OK',
short_msg => 'All VMTools are OK'
);
} else { } else {
$self->{output}->output_add(severity => 'OK', $self->{output}->output_add(
short_msg => 'VMTools are OK'); severity => 'OK',
short_msg => 'VMTools are OK'
);
} }
my %not_installed = (); my %not_installed = ();
my %not_running = (); my %not_running = ();
my %not_up2date = (); my %not_up2date = ();
@ -113,14 +120,16 @@ sub run {
my $output = "VM '" . $vm_name . "' not connected. Current Connection State: '$response->{data}->{$vm_id}->{connection_state}'."; my $output = "VM '" . $vm_name . "' not connected. Current Connection State: '$response->{data}->{$vm_id}->{connection_state}'.";
if ($multiple == 0 || if ($multiple == 0 ||
!$self->{output}->is_status(value => $self->{option_results}->{disconnect_status}, compare => 'ok', litteral => 1)) { !$self->{output}->is_status(value => $self->{option_results}->{disconnect_status}, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(severity => $self->{option_results}->{disconnect_status}, $self->{output}->output_add(
short_msg => $output); severity => $self->{option_results}->{disconnect_status},
short_msg => $output
);
} }
next; next;
} }
next if (defined($self->{option_results}->{nopoweredon_skip}) && next if (defined($self->{option_results}->{nopoweredon_skip}) &&
$options{custom}->vm_is_running(power => $response->{data}->{$vm_id}->{power_state}) == 0); $options{custom}->vm_is_running(power => $response->{data}->{$vm_id}->{power_state}) == 0);
next if (!defined($response->{data}->{$vm_id}->{tools_status})); next if (!defined($response->{data}->{$vm_id}->{tools_status}));
@ -133,26 +142,32 @@ sub run {
$not_up2date{$vm_name} = defined($response->{data}->{$vm_id}->{'config.annotation'}) ? $response->{data}->{$vm_id}->{'config.annotation'} : ''; $not_up2date{$vm_name} = defined($response->{data}->{$vm_id}->{'config.annotation'}) ? $response->{data}->{$vm_id}->{'config.annotation'} : '';
} }
} }
if (scalar(keys %not_up2date) > 0 && if (scalar(keys %not_up2date) > 0 &&
!$self->{output}->is_status(value => $self->{option_results}->{tools_notupd2date_status}, compare => 'ok', litteral => 1)) { !$self->{output}->is_status(value => $self->{option_results}->{tools_notupd2date_status}, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(severity => $self->{option_results}->{tools_notupd2date_status}, $self->{output}->output_add(
short_msg => sprintf('%d VM with VMTools not up-to-date', scalar(keys %not_up2date))); severity => $self->{option_results}->{tools_notupd2date_status},
short_msg => sprintf('%d VM with VMTools not up-to-date', scalar(keys %not_up2date))
);
$self->display_verbose(label => 'vmtools not up-to-date:', vms => \%not_up2date, custom => $options{custom}); $self->display_verbose(label => 'vmtools not up-to-date:', vms => \%not_up2date, custom => $options{custom});
} }
if (scalar(keys %not_running) > 0 && if (scalar(keys %not_running) > 0 &&
!$self->{output}->is_status(value => $self->{option_results}->{tools_notrunning_status}, compare => 'ok', litteral => 1)) { !$self->{output}->is_status(value => $self->{option_results}->{tools_notrunning_status}, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(severity => $self->{option_results}->{tools_notrunning_status}, $self->{output}->output_add(
short_msg => sprintf('%d VM with VMTools not running', scalar(keys %not_running))); severity => $self->{option_results}->{tools_notrunning_status},
short_msg => sprintf('%d VM with VMTools not running', scalar(keys %not_running))
);
$self->display_verbose(label => 'vmtools not running:', vms => \%not_running, custom => $options{custom}); $self->display_verbose(label => 'vmtools not running:', vms => \%not_running, custom => $options{custom});
} }
if (scalar(keys %not_installed) > 0 && if (scalar(keys %not_installed) > 0 &&
!$self->{output}->is_status(value => $self->{option_results}->{tools_notinstalled_status}, compare => 'ok', litteral => 1)) { !$self->{output}->is_status(value => $self->{option_results}->{tools_notinstalled_status}, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(severity => $self->{option_results}->{tools_notinstalled_status}, $self->{output}->output_add(
short_msg => sprintf('%d VM with VMTools not installed', scalar(keys %not_installed))); severity => $self->{option_results}->{tools_notinstalled_status},
short_msg => sprintf('%d VM with VMTools not installed', scalar(keys %not_installed))
);
$self->display_verbose(label => 'vmtools not installed:', vms => \%not_installed, custom => $options{custom}); $self->display_verbose(label => 'vmtools not installed:', vms => \%not_installed, custom => $options{custom});
} }
if ($multiple == 1) { if ($multiple == 1) {
my $total = scalar(keys %not_up2date) + scalar(keys %not_running) + scalar(keys %not_installed); my $total = scalar(keys %not_up2date) + scalar(keys %not_running) + scalar(keys %not_installed);
$self->{output}->perfdata_add( $self->{output}->perfdata_add(
@ -174,7 +189,7 @@ sub run {
min => 0, max => $total min => 0, max => $total
); );
} }
$self->{output}->display(); $self->{output}->display();
$self->{output}->exit(); $self->{output}->exit();
} }
@ -226,6 +241,10 @@ Status if VM disconnected (default: 'unknown').
Skip check if VM is not poweredOn. Skip check if VM is not poweredOn.
=item B<--empty-continue>
Ask to the connector that an empty response is ok.
=item B<--display-description> =item B<--display-description>
Display virtual machine description. Display virtual machine description.

View File

@ -33,8 +33,9 @@ sub new {
$self->{modes} = { $self->{modes} = {
'alarm-datacenter' => 'apps::vmware::connector::mode::alarmdatacenter', 'alarm-datacenter' => 'apps::vmware::connector::mode::alarmdatacenter',
'alarm-host' => 'apps::vmware::connector::mode::alarmhost', 'alarm-host' => 'apps::vmware::connector::mode::alarmhost',
'countvm-host' => 'apps::vmware::connector::mode::countvmhost', 'countvm-host' => 'apps::vmware::connector::mode::countvmhost',
'cpu-host' => 'apps::vmware::connector::mode::cpuhost', 'cpu-cluster' => 'apps::vmware::connector::mode::cpucluster',
'cpu-host' => 'apps::vmware::connector::mode::cpuhost',
'cpu-vm' => 'apps::vmware::connector::mode::cpuvm', 'cpu-vm' => 'apps::vmware::connector::mode::cpuvm',
'datastore-countvm' => 'apps::vmware::connector::mode::datastorecountvm', 'datastore-countvm' => 'apps::vmware::connector::mode::datastorecountvm',
'datastore-host' => 'apps::vmware::connector::mode::datastorehost', 'datastore-host' => 'apps::vmware::connector::mode::datastorehost',
@ -47,6 +48,7 @@ sub new {
'discovery' => 'apps::vmware::connector::mode::discovery', 'discovery' => 'apps::vmware::connector::mode::discovery',
'getmap' => 'apps::vmware::connector::mode::getmap', 'getmap' => 'apps::vmware::connector::mode::getmap',
'health-host' => 'apps::vmware::connector::mode::healthhost', 'health-host' => 'apps::vmware::connector::mode::healthhost',
'licenses' => 'apps::vmware::connector::mode::licenses',
'limit-vm' => 'apps::vmware::connector::mode::limitvm', 'limit-vm' => 'apps::vmware::connector::mode::limitvm',
'list-clusters' => 'apps::vmware::connector::mode::listclusters', 'list-clusters' => 'apps::vmware::connector::mode::listclusters',
'list-datacenters' => 'apps::vmware::connector::mode::listdatacenters', 'list-datacenters' => 'apps::vmware::connector::mode::listdatacenters',
@ -63,6 +65,7 @@ sub new {
'status-cluster' => 'apps::vmware::connector::mode::statuscluster', 'status-cluster' => 'apps::vmware::connector::mode::statuscluster',
'status-host' => 'apps::vmware::connector::mode::statushost', 'status-host' => 'apps::vmware::connector::mode::statushost',
'status-vm' => 'apps::vmware::connector::mode::statusvm', 'status-vm' => 'apps::vmware::connector::mode::statusvm',
'storage-host' => 'apps::vmware::connector::mode::storagehost',
'swap-host' => 'apps::vmware::connector::mode::swaphost', 'swap-host' => 'apps::vmware::connector::mode::swaphost',
'swap-vm' => 'apps::vmware::connector::mode::swapvm', 'swap-vm' => 'apps::vmware::connector::mode::swapvm',
'thinprovisioning-vm' => 'apps::vmware::connector::mode::thinprovisioningvm', 'thinprovisioning-vm' => 'apps::vmware::connector::mode::thinprovisioningvm',