From 1c6ea8e3ab2c46a817e74c0721d49fe0cdddf95c Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 10 Nov 2020 16:37:29 +0100 Subject: [PATCH] Oracle ovm (#2337) --- .../apps/oracle/ovm/api/custom/rest.pm | 192 +++++++++++++ .../apps/oracle/ovm/api/mode/discovery.pm | 158 +++++++++++ .../apps/oracle/ovm/api/mode/fileservers.pm | 201 ++++++++++++++ .../apps/oracle/ovm/api/mode/manager.pm | 159 +++++++++++ .../apps/oracle/ovm/api/mode/serverpools.pm | 253 ++++++++++++++++++ .../apps/oracle/ovm/api/mode/servers.pm | 229 ++++++++++++++++ .../apps/oracle/ovm/api/mode/vm.pm | 177 ++++++++++++ .../apps/oracle/ovm/api/plugin.pm | 54 ++++ 8 files changed, 1423 insertions(+) create mode 100644 centreon-plugins/apps/oracle/ovm/api/custom/rest.pm create mode 100644 centreon-plugins/apps/oracle/ovm/api/mode/discovery.pm create mode 100644 centreon-plugins/apps/oracle/ovm/api/mode/fileservers.pm create mode 100644 centreon-plugins/apps/oracle/ovm/api/mode/manager.pm create mode 100644 centreon-plugins/apps/oracle/ovm/api/mode/serverpools.pm create mode 100644 centreon-plugins/apps/oracle/ovm/api/mode/servers.pm create mode 100644 centreon-plugins/apps/oracle/ovm/api/mode/vm.pm create mode 100644 centreon-plugins/apps/oracle/ovm/api/plugin.pm diff --git a/centreon-plugins/apps/oracle/ovm/api/custom/rest.pm b/centreon-plugins/apps/oracle/ovm/api/custom/rest.pm new file mode 100644 index 000000000..0ce4c7955 --- /dev/null +++ b/centreon-plugins/apps/oracle/ovm/api/custom/rest.pm @@ -0,0 +1,192 @@ +# +# Copyright 2020 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::oracle::ovm::api::custom::rest; + +use strict; +use warnings; +use centreon::plugins::http; +use JSON::XS; + +sub new { + my ($class, %options) = @_; + my $self = {}; + bless $self, $class; + + if (!defined($options{output})) { + print "Class Custom: Need to specify 'output' argument.\n"; + exit 3; + } + if (!defined($options{options})) { + $options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument."); + $options{output}->option_exit(); + } + + if (!defined($options{noptions})) { + $options{options}->add_options(arguments => { + 'api-username:s' => { name => 'api_username' }, + 'api-password:s' => { name => 'api_password' }, + 'hostname:s' => { name => 'hostname' }, + 'port:s' => { name => 'port' }, + 'proto:s' => { name => 'proto' }, + 'timeout:s' => { name => 'timeout' }, + 'unknown-http-status:s' => { name => 'unknown_http_status' }, + 'warning-http-status:s' => { name => 'warning_http_status' }, + 'critical-http-status:s' => { name => 'critical_http_status' } + }); + } + $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); + + $self->{output} = $options{output}; + $self->{http} = centreon::plugins::http->new(%options); + + return $self; +} + +sub set_options { + my ($self, %options) = @_; + + $self->{option_results} = $options{option_results}; +} + +sub set_defaults {} + +sub check_options { + my ($self, %options) = @_; + + $self->{option_results}->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 7002; + $self->{option_results}->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; + $self->{option_results}->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; + $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; + $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; + $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; + $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; + $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; + + if (!defined($self->{option_results}->{hostname}) || $self->{option_results}->{hostname} eq '') { + $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); + $self->{output}->option_exit(); + } + if ($self->{api_username} eq '') { + $self->{output}->add_option_msg(short_msg => 'Need to specify --api-username option.'); + $self->{output}->option_exit(); + } + if ($self->{api_password} eq '') { + $self->{output}->add_option_msg(short_msg => 'Need to specify --api-password option.'); + $self->{output}->option_exit(); + } + + return 0; +} + +sub settings { + my ($self, %options) = @_; + + return if (defined($self->{settings_done})); + $self->{http}->add_header(key => 'Accept', value => 'application/json'); + $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); + $self->{option_results}->{credentials} = 1; + $self->{option_results}->{basic} = 1; + $self->{option_results}->{username} = $self->{api_username}; + $self->{option_results}->{password} = $self->{api_password}; + $self->{http}->set_options(%{$self->{option_results}}); + $self->{settings_done} = 1; +} + +sub get_connection_info { + my ($self, %options) = @_; + + return $self->{option_results}->{hostname} . ":" . $self->{option_results}->{port}; +} + +sub request_api { + my ($self, %options) = @_; + + $self->settings(); + my ($content) = $self->{http}->request( + url_path => '/ovm/core/wsapi/rest' . $options{endpoint}, + unknown_status => $self->{unknown_http_status}, + warning_status => $self->{warning_http_status}, + critical_status => $self->{critical_http_status}, + get_param => $options{get_param} + ); + + if (!defined($content) || $content eq '') { + $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); + $self->{output}->option_exit(); + } + + my $decoded; + eval { + $decoded = JSON::XS->new->allow_nonref(1)->utf8->decode($content); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); + $self->{output}->option_exit(); + } + + return $decoded; +} + +1; + +__END__ + +=head1 NAME + +Oracle OVM Rest API + +=head1 REST API OPTIONS + +Oracle OVM Rest API + +=over 8 + +=item B<--hostname> + +Set hostname. + +=item B<--port> + +Port used (Default: 7002) + +=item B<--proto> + +Specify https if needed (Default: 'https') + +=item B<--api-username> + +API username. + +=item B<--api-password> + +API password. + +=item B<--timeout> + +Set timeout in seconds (Default: 30). + +=back + +=head1 DESCRIPTION + +B. + +=cut diff --git a/centreon-plugins/apps/oracle/ovm/api/mode/discovery.pm b/centreon-plugins/apps/oracle/ovm/api/mode/discovery.pm new file mode 100644 index 000000000..0f76af69e --- /dev/null +++ b/centreon-plugins/apps/oracle/ovm/api/mode/discovery.pm @@ -0,0 +1,158 @@ +# +# Copyright 2020 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::oracle::ovm::api::mode::discovery; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use JSON::XS; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'resource-type:s' => { name => 'resource_type' }, + 'prettify' => { name => 'prettify' } + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); + + if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { + $self->{option_results}->{resource_type} = 'server'; + } + if ($self->{option_results}->{resource_type} !~ /^server|vm$/) { + $self->{output}->add_option_msg(short_msg => 'unknown resource type'); + $self->{output}->option_exit(); + } +} + +sub discovery_vm { + my ($self, %options) = @_; + + my $vms = $options{custom}->request_api(endpoint => '/Vm'); + + my $disco_data = []; + foreach my $vm (@$vms) { + my $node = {}; + $node->{uuid} = $vm->{id}->{value}; + $node->{name} = $vm->{name}; + $node->{description} = $vm->{description}; + $node->{running_state} = lc($vm->{vmRunState}); + $node->{os_type} = $vm->{osType}; + $node->{server_pool_uuid} = $vm->{serverPoolId}->{value}; + $node->{server_pool_name} = $vm->{serverPoolId}->{name}; + $node->{server_uuid} = $vm->{serverId}->{value}; + $node->{server_name} = $vm->{serverId}->{name}; + + push @$disco_data, $node; + } + + return $disco_data; +} + +sub discovery_server { + my ($self, %options) = @_; + + my $servers = $options{custom}->request_api(endpoint => '/Server'); + + my $disco_data = []; + foreach my $server (@$servers) { + my $node = {}; + $node->{uuid} = $server->{id}->{value}; + $node->{name} = $server->{name}; + $node->{description} = $server->{description}; + $node->{running_state} = lc($server->{serverRunState}); + $node->{ip_address} = $server->{ipAddress}; + $node->{hostname} = $server->{hostname}; + $node->{serial_number} = $server->{serialNumber}; + $node->{server_pool_uuid} = $server->{serverPoolId}->{value}; + $node->{server_pool_name} = $server->{serverPoolId}->{name}; + + push @$disco_data, $node; + } + + return $disco_data; +} + +sub run { + my ($self, %options) = @_; + + my $disco_stats; + $disco_stats->{start_time} = time(); + + my $results = []; + if ($self->{option_results}->{resource_type} eq 'vm') { + $results = $self->discovery_vm( + custom => $options{custom} + ); + } else { + $results = $self->discovery_server( + custom => $options{custom} + ); + } + + $disco_stats->{end_time} = time(); + $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; + $disco_stats->{discovered_items} = scalar(@$results); + $disco_stats->{results} = $results; + + my $encoded_data; + eval { + if (defined($self->{option_results}->{prettify})) { + $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); + } else { + $encoded_data = JSON::XS->new->utf8->encode($disco_stats); + } + }; + if ($@) { + $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; + } + + $self->{output}->output_add(short_msg => $encoded_data); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); + $self->{output}->exit(); +} + +1; + +__END__ + +=head1 MODE + +Resources discovery. + +=over 8 + +=item B<--resource-type> + +Choose the type of resources to discover (Can be: 'vm', 'server'). + +=back + +=cut diff --git a/centreon-plugins/apps/oracle/ovm/api/mode/fileservers.pm b/centreon-plugins/apps/oracle/ovm/api/mode/fileservers.pm new file mode 100644 index 000000000..e3f2a321e --- /dev/null +++ b/centreon-plugins/apps/oracle/ovm/api/mode/fileservers.pm @@ -0,0 +1,201 @@ +# +# Copyright 2020 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::oracle::ovm::api::mode::fileservers; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space}); + return sprintf( + 'space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_space}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space} + ); +} + +sub fileserver_long_output { + my ($self, %options) = @_; + + return "checking file server '" . $options{instance_value}->{name} . "'"; +} + +sub prefix_fileserver_output { + my ($self, %options) = @_; + + return "File server '" . $options{instance_value}->{name} . "' "; +} + +sub prefix_fs_output { + my ($self, %options) = @_; + + return "filesystem '" . $options{instance_value}->{name} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'fileservers', type => 3, cb_prefix_output => 'prefix_fileserver_output', cb_long_output => 'fileserver_long_output', indent_long_output => ' ', message_multiple => 'All file servers are ok', + group => [ + { name => 'filesystems', type => 1, display_long => 1, cb_prefix_output => 'prefix_fs_output', message_multiple => 'filesystems are ok', skipped_code => { -10 => 1 } } + ] + } + ]; + + $self->{maps_counters}->{filesystems} = [ + { label => 'space-usage', nlabel => 'serverpool.space.usage.bytes', set => { + key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], + closure_custom_output => $self->can('custom_usage_output'), + perfdatas => [ + { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } + ] + } + }, + { label => 'space-usage-free', nlabel => 'serverpool.space.free.bytes', display_ok => 0, set => { + key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], + closure_custom_output => $self->can('custom_usage_output'), + perfdatas => [ + { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } + ] + } + }, + { label => 'space-usage-prct', nlabel => 'serverpool.space.usage.percentage', display_ok => 0, set => { + key_values => [ { name => 'prct_used_space' }, { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], + closure_custom_output => $self->can('custom_usage_output'), + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%', 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 => { + 'filter-fileserver-name:s' => { name => 'filter_fileserver_name' }, + 'filter-filesystem-name:s' => { name => 'filter_filesystem_name' } + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $manager = $options{custom}->request_api(endpoint => '/Manager'); + if ($manager->[0]->{managerRunState} ne 'RUNNING') { + $self->{output}->add_option_msg(short_msg => 'manager is not running.'); + $self->{output}->option_exit(); + } + + my $fileservers = $options{custom}->request_api(endpoint => '/FileServer'); + my $filesystems = $options{custom}->request_api(endpoint => '/FileSystem'); + + $self->{fileservers} = {}; + foreach my $fileserver (@$fileservers) { + my $name = $fileserver->{id}->{value}; + $name = $fileserver->{name} + if (defined($fileserver->{name}) && $fileserver->{name} ne ''); + + if (defined($self->{option_results}->{filter_fileserver_name}) && $self->{option_results}->{filter_fileserver_name} ne '' && + $name !~ /$self->{option_results}->{filter_fileserver_name}/) { + $self->{output}->output_add(long_msg => "skipping file server '" . $name . "': no matching filter.", debug => 1); + next; + } + + $self->{fileservers}->{$name} = { + name => $name, + filesystems => {} + }; + + foreach my $filesystem (@{$fileserver->{fileSystemIds}}) { + foreach my $target (@$filesystems) { + if ($filesystem->{value} eq $target->{id}->{value}) { + my $fs_name = $target->{id}->{value}; + $fs_name = $target->{name} + if (defined($target->{name}) && $target->{name} ne ''); + + if (defined($self->{option_results}->{filter_filesystem_name}) && $self->{option_results}->{filter_filesystem_name} ne '' && + $fs_name !~ /$self->{option_results}->{filter_filesystem_name}/) { + $self->{output}->output_add(long_msg => "skipping file system '" . $fs_name . "': no matching filter.", debug => 1); + next; + } + + my $total_space = $target->{size}; + my $usable_space = $target->{freeSize}; + $self->{fileservers}->{$name}->{filesystems}->{$fs_name} = { + name => $fs_name, + total_space => $total_space, + used_space => $total_space - $usable_space, + free_space => $usable_space, + prct_used_space => ($total_space - $usable_space) * 100 / $total_space, + prct_free_space => $usable_space * 100 / $total_space + }; + last; + } + } + } + } +} + +1; + +__END__ + +=head1 MODE + +Check file servers. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^space-usage$' + +=item B<--filter-fileserver-name> + +Filter file servers by name (can be a regexp). + +=item B<--filter-filesystem-name> + +Filter file systems by name (can be a regexp). + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'space-usage' (B), 'space-usage-free' (B), 'space-usage-prct' (%). + +=back + +=cut diff --git a/centreon-plugins/apps/oracle/ovm/api/mode/manager.pm b/centreon-plugins/apps/oracle/ovm/api/mode/manager.pm new file mode 100644 index 000000000..4b9e8e848 --- /dev/null +++ b/centreon-plugins/apps/oracle/ovm/api/mode/manager.pm @@ -0,0 +1,159 @@ +# +# Copyright 2020 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::oracle::ovm::api::mode::manager; + +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}; +} + +sub prefix_manager_output { + my ($self, %options) = @_; + + return "Manager '" . $options{instance_value}->{name} . "' "; +} + +sub prefix_jobs_output { + my ($self, %options) = @_; + + return 'Jobs '; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'manager', type => 0, cb_prefix_output => 'prefix_manager_output', skipped_code => { -10 => 1 } }, + { name => 'jobs', type => 0, cb_prefix_output => 'prefix_jobs_output', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{manager} = [ + { label => 'status', type => 2, critical_default => '%{status} !~ /running/i', set => { + key_values => [ { name => 'status' }, { name => 'name' } ], + 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}->{jobs} = [ + { label => 'jobs-succeeded', nlabel => 'manager.jobs.succeeded.count', set => { + key_values => [ { name => 'success' }, { name => 'name' } ], + output_template => 'succeeded: %s', + perfdatas => [ + { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } + ] + } + }, + { label => 'jobs-failed', nlabel => 'manager.jobs.failed.count', set => { + key_values => [ { name => 'failure' }, { name => 'name' } ], + output_template => 'failed: %s', + perfdatas => [ + { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } + ] + } + } + ]; +} + +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 => { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $manager = $options{custom}->request_api(endpoint => '/Manager'); + my $jobs = $options{custom}->request_api(endpoint => '/Job'); + + my $name = $manager->[0]->{id}->{value}; + $name = $manager->[0]->{name} + if (defined($manager->[0]->{name}) && $manager->[0]->{name} ne ''); + + $self->{manager} = { + name => $name, + status => lc($manager->[0]->{managerRunState}) + }; + + $self->{jobs} = { + name => $name, + success => 0, + failure => 0 + }; + foreach (@$jobs) { + $self->{jobs}->{ lc($_->{jobSummaryState}) }++ + if (defined($self->{jobs}->{ lc($_->{jobSummaryState}) })); + } +} + +1; + +__END__ + +=head1 MODE + +Check manager. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='status' + +=item B<--unknown-status> + +Set unknown threshold for status. +Can used special variables like: %{status}, %{name} + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{status}, %{name} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} !~ /running/i'). +Can used special variables like: %{status}, %{name} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'jobs-succeeded', 'jobs-failed'. + +=back + +=cut diff --git a/centreon-plugins/apps/oracle/ovm/api/mode/serverpools.pm b/centreon-plugins/apps/oracle/ovm/api/mode/serverpools.pm new file mode 100644 index 000000000..baf14f64b --- /dev/null +++ b/centreon-plugins/apps/oracle/ovm/api/mode/serverpools.pm @@ -0,0 +1,253 @@ +# +# Copyright 2020 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::oracle::ovm::api::mode::serverpools; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_memory}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_memory}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_memory}); + return sprintf( + 'memory usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_memory}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_memory} + ); +} + +sub pool_long_output { + my ($self, %options) = @_; + + return "checking server pool '" . $options{instance_value}->{name} . "'"; +} + +sub prefix_pool_output { + my ($self, %options) = @_; + + return "Server pool '" . $options{instance_value}->{name} . "' "; +} + +sub prefix_servers_output { + my ($self, %options) = @_; + + return 'servers '; +} + +sub prefix_vm_output { + my ($self, %options) = @_; + + return 'virtual machines '; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'pools', type => 3, cb_prefix_output => 'prefix_pool_output', cb_long_output => 'pool_long_output', indent_long_output => ' ', message_multiple => 'All server pools are ok', + group => [ + { name => 'servers', type => 0, cb_prefix_output => 'prefix_servers_output' }, + { name => 'vm', type => 0, cb_prefix_output => 'prefix_vm_output' }, + { name => 'memory', type => 0 } + ] + } + ]; + + $self->{maps_counters}->{servers} = [ + { label => 'servers-running', nlabel => 'serverpool.servers.running.count', set => { + key_values => [ { name => 'running' }, { name => 'total' } ], + output_template => 'running: %d', + perfdatas => [ + { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } + ] + } + }, + { label => 'servers-stopped', nlabel => 'serverpool.servers.stopped.count', set => { + key_values => [ { name => 'stopped' }, { name => 'total' } ], + output_template => 'stopped: %d', + perfdatas => [ + { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } + ] + } + } + ]; + + $self->{maps_counters}->{vm} = [ + { label => 'vm-running', nlabel => 'serverpool.vm.running.count', set => { + key_values => [ { name => 'running' }, { name => 'total' } ], + output_template => 'running: %d', + perfdatas => [ + { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } + ] + } + }, + { label => 'vm-stopped', nlabel => 'serverpool.vm.stopped.count', set => { + key_values => [ { name => 'stopped' }, { name => 'total' } ], + output_template => 'stopped: %d', + perfdatas => [ + { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } + ] + } + } + ]; + + $self->{maps_counters}->{memory} = [ + { label => 'memory-usage', nlabel => 'serverpool.memory.usage.bytes', set => { + key_values => [ { name => 'used_memory' }, { name => 'free_memory' }, { name => 'prct_used_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], + closure_custom_output => $self->can('custom_usage_output'), + perfdatas => [ + { template => '%d', min => 0, max => 'total_memory', unit => 'B', cast_int => 1, label_extra_instance => 1 } + ] + } + }, + { label => 'memory-usage-free', nlabel => 'serverpool.memory.free.bytes', display_ok => 0, set => { + key_values => [ { name => 'free_memory' }, { name => 'used_memory' }, { name => 'prct_used_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], + closure_custom_output => $self->can('custom_usage_output'), + perfdatas => [ + { template => '%d', min => 0, max => 'total_memory', unit => 'B', cast_int => 1, label_extra_instance => 1 } + ] + } + }, + { label => 'memory-usage-prct', nlabel => 'serverpool.memory.usage.percentage', display_ok => 0, set => { + key_values => [ { name => 'prct_used_memory' }, { name => 'used_memory' }, { name => 'free_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], + closure_custom_output => $self->can('custom_usage_output'), + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%', 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 => { + 'filter-server-pool-name:s' => { name => 'filter_server_pool_name' } + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $manager = $options{custom}->request_api(endpoint => '/Manager'); + if ($manager->[0]->{managerRunState} ne 'RUNNING') { + $self->{output}->add_option_msg(short_msg => 'manager is not running.'); + $self->{output}->option_exit(); + } + + my $pools = $options{custom}->request_api(endpoint => '/ServerPool'); + my $vms = $options{custom}->request_api(endpoint => '/Vm'); + my $servers = $options{custom}->request_api(endpoint => '/Server'); + + $self->{pools} = {}; + foreach (@$pools) { + my $name = $_->{id}->{value}; + $name = $_->{name} + if (defined($_->{name}) && $_->{name} ne ''); + + if (defined($self->{option_results}->{filter_server_pool_name}) && $self->{option_results}->{filter_server_pool_name} ne '' && + $name !~ /$self->{option_results}->{filter_server_pool_name}/) { + $self->{output}->output_add(long_msg => "skipping server pool '" . $name . "': no matching filter.", debug => 1); + next; + } + + $self->{pools}->{$name} = { + name => $name, + memory => { + total_memory => 0, + free_memory => 0 + }, + servers => { + total => 0, running => 0, stopped => 0 + }, + vm => { + total => 0, running => 0, stopped => 0 + } + }; + + foreach my $server (@{$_->{serverIds}}) { + foreach my $target (@$servers) { + if ($server->{value} eq $target->{id}->{value}) { + $self->{pools}->{$name}->{memory}->{total_memory} += ($target->{memory} * 1024 * 1024); + $self->{pools}->{$name}->{memory}->{free_memory} += ($target->{usableMemory} * 1024 * 1024); + $self->{pools}->{$name}->{servers}->{ lc($target->{serverRunState}) }++ + if (defined($self->{pools}->{$name}->{servers}->{ lc($target->{serverRunState}) })); + $self->{pools}->{$name}->{servers}->{total}++; + last; + } + } + } + + foreach my $vm (@{$_->{vmIds}}) { + foreach my $target (@$vms) { + if ($vm->{value} eq $target->{id}->{value}) { + $self->{pools}->{$name}->{vm}->{ lc($target->{vmRunState}) }++ + if (defined($self->{pools}->{$name}->{vm}->{ lc($target->{vmRunState}) })); + $self->{pools}->{$name}->{vm}->{total}++; + last; + } + } + } + + $self->{pools}->{$name}->{memory}->{used_memory} = $self->{pools}->{$name}->{memory}->{total_memory} - $self->{pools}->{$name}->{memory}->{free_memory}; + $self->{pools}->{$name}->{memory}->{prct_used_memory} = $self->{pools}->{$name}->{memory}->{used_memory} * 100 / $self->{pools}->{$name}->{memory}->{total_memory}; + $self->{pools}->{$name}->{memory}->{prct_free_memory} = 100 - $self->{pools}->{$name}->{memory}->{prct_used_memory}; + } +} + +1; + +__END__ + +=head1 MODE + +Check servers. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^memory-usage$' + +=item B<--filter-server-pool-name> + +Filter server pools by name (can be a regexp). + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'servers-running', 'servers-stopped', 'vm-running', 'vm-stopped', +'memory-usage' (B), 'memory-usage-free' (B), 'memory-usage-prct' (%). + +=back + +=cut diff --git a/centreon-plugins/apps/oracle/ovm/api/mode/servers.pm b/centreon-plugins/apps/oracle/ovm/api/mode/servers.pm new file mode 100644 index 000000000..ce220a40e --- /dev/null +++ b/centreon-plugins/apps/oracle/ovm/api/mode/servers.pm @@ -0,0 +1,229 @@ +# +# Copyright 2020 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::oracle::ovm::api::mode::servers; + +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 sprintf( + 'running state: %s [up2date: %s][maintenance: %s]', + $self->{result_values}->{running_state}, + $self->{result_values}->{up2date}, + $self->{result_values}->{is_maintenance} + ); +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_memory}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_memory}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_memory}); + return sprintf( + 'memory usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_memory}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_memory} + ); +} + +sub prefix_server_output { + my ($self, %options) = @_; + + return "Server '" . $options{instance_value}->{name} . "' "; +} + +sub prefix_global_output { + my ($self, %options) = @_; + + return 'Servers '; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, + { name => 'servers', type => 1, cb_prefix_output => 'prefix_server_output', message_multiple => 'All servers are ok', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'servers-running', nlabel => 'servers.running.count', display_ok => 0, set => { + key_values => [ { name => 'running' }, { name => 'total' } ], + output_template => 'running: %d', + perfdatas => [ + { template => '%d', min => 0, max => 'total' } + ] + } + }, + { label => 'servers-stopped', nlabel => 'servers.stopped.count', display_ok => 0, set => { + key_values => [ { name => 'stopped' }, { name => 'total' } ], + output_template => 'stopped: %d', + perfdatas => [ + { template => '%d', min => 0, max => 'total' } + ] + } + } + ]; + + $self->{maps_counters}->{servers} = [ + { label => 'status', threshold => 2, set => { + key_values => [ + { name => 'running_state' }, { name => 'up2date' }, + { name => 'is_maintenance' },{ name => 'name' } + ], + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + { label => 'memory-usage', nlabel => 'server.memory.usage.bytes', set => { + key_values => [ { name => 'used_memory' }, { name => 'free_memory' }, { name => 'prct_used_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], + closure_custom_output => $self->can('custom_usage_output'), + perfdatas => [ + { template => '%d', min => 0, max => 'total_memory', unit => 'B', cast_int => 1, label_extra_instance => 1 } + ] + } + }, + { label => 'memory-usage-free', nlabel => 'server.memory.free.bytes', display_ok => 0, set => { + key_values => [ { name => 'free_memory' }, { name => 'used_memory' }, { name => 'prct_used_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], + closure_custom_output => $self->can('custom_usage_output'), + perfdatas => [ + { template => '%d', min => 0, max => 'total_memory', unit => 'B', cast_int => 1, label_extra_instance => 1 } + ] + } + }, + { label => 'memory-usage-prct', nlabel => 'server.memory.usage.percentage', display_ok => 0, set => { + key_values => [ { name => 'prct_used_memory' }, { name => 'used_memory' }, { name => 'free_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], + closure_custom_output => $self->can('custom_usage_output'), + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%', 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 => { + 'filter-name:s' => { name => 'filter_name' } + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $manager = $options{custom}->request_api(endpoint => '/Manager'); + if ($manager->[0]->{managerRunState} ne 'RUNNING') { + $self->{output}->add_option_msg(short_msg => 'manager is not running.'); + $self->{output}->option_exit(); + } + + my $servers = $options{custom}->request_api(endpoint => '/Server'); + + $self->{global} = { running => 0, stopped => 0, total => 0 }; + $self->{servers} = {}; + foreach (@$servers) { + my $name = $_->{id}->{value}; + $name = $_->{name} + if (defined($_->{name}) && $_->{name} ne ''); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping server '" . $name . "': no matching filter.", debug => 1); + next; + } + + my $total_memory = $_->{memory} * 1024 * 1024; + my $usable_memory = $_->{usableMemory} * 1024 * 1024; + $self->{servers}->{$name} = { + name => $name, + running_state => lc($_->{serverRunState}), + is_maintenance => $_->{maintenanceMode} =~ /True|1/i ? 'yes' : 'no', + up2date => $_->{serverUpToDate} =~ /True|1/i ? 'yes' : 'no', + + total_memory => $total_memory, + used_memory => $total_memory - $usable_memory, + free_memory => $usable_memory, + prct_used_memory => ($total_memory - $usable_memory) * 100 / $total_memory, + prct_free_memory => $usable_memory * 100 / $total_memory + }; + $self->{global}->{ lc($_->{serverRunState}) }++ + if (defined($self->{global}->{ lc($_->{serverRunState}) })); + $self->{global}->{total}++; + } +} + +1; + +__END__ + +=head1 MODE + +Check servers. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^memory-usage$' + +=item B<--filter-name> + +Filter servers by name (can be a regexp). + +=item B<--unknown-status> + +Set unknown threshold for status. +Can used special variables like: %{running_status}, %{is_maintenance}, %{up2date}, %{name} + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{running_status}, %{is_maintenance}, %{up2date}, %{name} + +=item B<--critical-status> + +Set critical threshold for status. +Can used special variables like: %{running_status}, %{is_maintenance}, %{up2date}, %{name} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'servers-running', 'servers-stopped', +'memory-usage' (B), 'memory-usage-free' (B), 'memory-usage-prct' (%). + +=back + +=cut diff --git a/centreon-plugins/apps/oracle/ovm/api/mode/vm.pm b/centreon-plugins/apps/oracle/ovm/api/mode/vm.pm new file mode 100644 index 000000000..a212c702c --- /dev/null +++ b/centreon-plugins/apps/oracle/ovm/api/mode/vm.pm @@ -0,0 +1,177 @@ +# +# Copyright 2020 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::oracle::ovm::api::mode::vm; + +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 sprintf( + 'running state: %s', + $self->{result_values}->{running_state} + ); +} + +sub prefix_vm_output { + my ($self, %options) = @_; + + return "Virtual machine '" . $options{instance_value}->{name} . "' "; +} + +sub prefix_global_output { + my ($self, %options) = @_; + + return 'Virtual machines '; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, + { name => 'vm', type => 1, cb_prefix_output => 'prefix_vm_output', message_multiple => 'All virtual machines are ok', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'vm-running', nlabel => 'virtualmachines.running.count', display_ok => 0, set => { + key_values => [ { name => 'running' }, { name => 'total' } ], + output_template => 'running: %d', + perfdatas => [ + { template => '%d', min => 0, max => 'total' } + ] + } + }, + { label => 'vm-stopped', nlabel => 'virtualmachines.stopped.count', display_ok => 0, set => { + key_values => [ { name => 'stopped' }, { name => 'total' } ], + output_template => 'stopped: %d', + perfdatas => [ + { template => '%d', min => 0, max => 'total' } + ] + } + } + ]; + + $self->{maps_counters}->{vm} = [ + { label => 'status', threshold => 2, set => { + key_values => [ + { name => 'running_state' }, { name => 'name' } + ], + closure_custom_output => $self->can('custom_status_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 => { + 'filter-name:s' => { name => 'filter_name' } + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $manager = $options{custom}->request_api(endpoint => '/Manager'); + if ($manager->[0]->{managerRunState} ne 'RUNNING') { + $self->{output}->add_option_msg(short_msg => 'manager is not running.'); + $self->{output}->option_exit(); + } + + my $vms = $options{custom}->request_api(endpoint => '/Vm'); + + $self->{global} = { running => 0, stopped => 0, total => 0 }; + $self->{vm} = {}; + foreach (@$vms) { + my $name = $_->{id}->{value}; + $name = $_->{name} + if (defined($_->{name}) && $_->{name} ne ''); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping virtual machine '" . $name . "': no matching filter.", debug => 1); + next; + } + + $self->{vm}->{$name} = { + name => $name, + running_state => lc($_->{vmRunState}) + }; + $self->{global}->{ lc($_->{vmRunState}) }++ + if (defined($self->{global}->{ lc($_->{vmRunState}) })); + $self->{global}->{total}++; + } +} + +1; + +__END__ + +=head1 MODE + +Check virtual machines. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='status' + +=item B<--filter-name> + +Filter virtual machines by name (can be a regexp). + +=item B<--unknown-status> + +Set unknown threshold for status. +Can used special variables like: %{running_status}, %{name} + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{running_status}, %{name} + +=item B<--critical-status> + +Set critical threshold for status. +Can used special variables like: %{running_status}, %{name} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'vm-running', 'vm-stopped'. + +=back + +=cut diff --git a/centreon-plugins/apps/oracle/ovm/api/plugin.pm b/centreon-plugins/apps/oracle/ovm/api/plugin.pm new file mode 100644 index 000000000..b328b20e7 --- /dev/null +++ b/centreon-plugins/apps/oracle/ovm/api/plugin.pm @@ -0,0 +1,54 @@ +# +# Copyright 2020 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::oracle::ovm::api::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_custom); + +sub new { + my ( $class, %options ) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '0.1'; + $self->{modes} = { + 'discovery' => 'apps::oracle::ovm::api::mode::discovery', + 'file-servers' => 'apps::oracle::ovm::api::mode::fileservers', + 'manager' => 'apps::oracle::ovm::api::mode::manager', + 'server-pools' => 'apps::oracle::ovm::api::mode::serverpools', + 'servers' => 'apps::oracle::ovm::api::mode::servers', + 'vm' => 'apps::oracle::ovm::api::mode::vm' + }; + + $self->{custom_modes}->{rest} = 'apps::oracle::ovm::api::custom::rest'; + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Oracle VM Manager using API. + +=cut