# # Copyright 2019 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::snapshotvm; use base qw(centreon::plugins::mode); use strict; use warnings; use Date::Parse; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { "vm-hostname:s" => { name => 'vm_hostname' }, "filter" => { name => 'filter' }, "scope-datacenter:s" => { name => 'scope_datacenter' }, "scope-cluster:s" => { name => 'scope_cluster' }, "scope-host:s" => { name => 'scope_host' }, "filter-description:s" => { name => 'filter_description' }, "filter-os:s" => { name => 'filter_os' }, "display-description" => { name => 'display_description' }, "check-consolidation" => { name => 'check_consolidation' }, "nopoweredon-skip" => { name => 'nopoweredon_skip' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "disconnect-status:s" => { name => 'disconnect_status', default => 'unknown' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); foreach my $label (('warning', 'critical')) { if (($self->{perfdata}->threshold_validate(label => $label, value => $self->{option_results}->{$label})) == 0) { my ($label_opt) = $label; $label_opt =~ tr/_/-/; $self->{output}->add_option_msg(short_msg => "Wrong " . $label_opt . " threshold '" . $self->{option_results}->{$label} . "'."); $self->{output}->option_exit(); } } if ($self->{output}->is_litteral_status(status => $self->{option_results}->{disconnect_status}) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong disconnect-status option '" . $self->{option_results}->{disconnect_status} . "'."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'snapshotvm'); my $multiple = 0; my %vm_consolidate = (); my %vm_errors = (warning => {}, critical => {}); if (scalar(keys %{$response->{data}}) > 1) { $multiple = 1; } if ($multiple == 1) { $self->{output}->output_add(severity => 'OK', short_msg => sprintf("All snapshots are ok")); } else { $self->{output}->output_add(severity => 'OK', short_msg => sprintf("Snapshot(s) OK")); } foreach my $vm_id (sort keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; 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}'."; if ($multiple == 0 || !$self->{output}->is_status(value => $self->{option_results}->{disconnect_status}, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $self->{option_results}->{disconnect_status}, short_msg => $output); } next; } next if (defined($self->{option_results}->{nopoweredon_skip}) && $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) { $vm_consolidate{$response->{data}->{$vm_id}->{name}} = 1; } foreach (@{$response->{data}->{$vm_id}->{snapshosts}}) { my $create_time = Date::Parse::str2time($_->{create_time}); if (!defined($create_time)) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Can't Parse date '" . $_->{create_time} . "' for vm '" . $vm_name . "'"); next; } my $diff_time = time() - $create_time; my $days = int($diff_time / 60 / 60 / 24); my $exit = $self->{perfdata}->threshold_check(value => $diff_time, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); my $prefix_msg = "'$vm_name'"; if (defined($self->{display_description}) && defined($response->{data}->{$vm_id}->{'config.annotation'}) && $response->{data}->{$vm_id}->{'config.annotation'} ne '') { $prefix_msg .= ' [' . $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}) . ']'; } my $suffix_msg = ''; if (defined($_->{description}) && $_->{description} ne '') { $suffix_msg = ' [' . $options{custom}->strip_cr(value => $_->{description}) . ']'; } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $vm_errors{$exit}->{$vm_name} = 1; $self->{output}->output_add(long_msg => "$prefix_msg snapshot create time: " . $_->{create_time} . $suffix_msg); } } } $self->{output}->perfdata_add(label => 'num_warning', value => scalar(keys %{$vm_errors{warning}}), min => 0); $self->{output}->perfdata_add(label => 'num_critical', value => scalar(keys %{$vm_errors{critical}}), min => 0); if (scalar(keys %{$vm_errors{warning}}) > 0) { $self->{output}->output_add(severity => 'WARNING', short_msg => sprintf('Snapshots for VM older than %d days: [%s]', ($self->{option_results}->{warning} / 86400), join('] [', sort keys %{$vm_errors{warning}}))); } if (scalar(keys %{$vm_errors{critical}}) > 0) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf('Snapshots for VM older than %d days: [%s]', ($self->{option_results}->{critical} / 86400), join('] [', sort keys %{$vm_errors{critical}}))); } if (scalar(keys %vm_consolidate) > 0) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf('VMs need consolidation: [%s]', join('] [', sort keys %vm_consolidate))); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check virtual machine snapshots. =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be 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<--scope-host> Search in following host(s) (can be a regexp). =item B<--display-description> Display virtual machine description. =item B<--check-consolidation> Check if VM needs consolidation (since vsphere 5.0). =item B<--disconnect-status> Status if VM disconnected (default: 'unknown'). =item B<--nopoweredon-skip> Skip check if VM is not poweredOn. =item B<--warning> Threshold warning in seconds. =item B<--critical> Threshold critical in seconds. =back =cut