[CTOR-284] new Datacore plugin with rest api (#4896)

Co-authored-by: Sophie Depassio <sdepassio@centreon.com>
This commit is contained in:
Evan-Adam 2024-03-11 11:25:35 +01:00 committed by GitHub
parent 058620c545
commit 321806011f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 1232 additions and 26 deletions

View File

@ -1,14 +1,17 @@
--filter-vdom
--force-counters32
Centreon
Fortinet
Datacore
Fortigate
Fortinet
license-instances-usage-prct
MBean
OID
oneaccess-sys-mib
perfdata
powershell
proto
Sansymphony
queue-messages-inflighted
SNMP
space-usage-prct

View File

@ -30,10 +30,10 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 16
node-version: 20
- name: Install Mockoon CLI
run: npm install -g -D @mockoon/cli@3.1.0
run: npm install -g -D @mockoon/cli@6.2.0
- name: Install perl dependencies
uses: shogo82148/actions-setup-perl@28eae78d12c2bba1163aec45d123f6d9228bc307 # v1.29.0

View File

@ -943,9 +943,9 @@ List of methods:
* **new**: class constructor. Overload if you need to add some specific options
or to use a statefile.
* **check_options**: overload if you need to check your specific options.
* **manage_selection**: overload if *mandatory*. Method to get informations for
* **manage_selection**: overload is *mandatory*. Method to get informations for
the equipment.
* **set_counters**: overload if **mandatory**. Method to configure counters.
* **set_counters**: overload is **mandatory**. Method to configure counters.
**Class hardware**

View File

@ -0,0 +1,4 @@
{
"dependencies": [
]
}

View File

@ -0,0 +1,9 @@
{
"pkg_name": "centreon-plugin-Hardware-Storage-DataCore-Sansymphony-Restapi",
"pkg_summary": "Centreon Plugin",
"plugin_name": "centreon_datacore_api.pl",
"files": [
"centreon/plugins/script_custom.pm",
"storage/datacore/api/"
]
}

View File

@ -0,0 +1,4 @@
{
"dependencies": [
]
}

View File

@ -311,6 +311,14 @@ sub backtick {
return (0, join("\n", @output), $return_code);
}
sub is_empty {
my $value = shift;
if (!defined($value) or $value eq '') {
return 1;
}
return 0;
}
sub trim {
my ($value) = $_[0];

View File

@ -0,0 +1,172 @@
#
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package storage::datacore::restapi::custom::api;
use strict;
use warnings;
use centreon::plugins::http;
use centreon::plugins::statefile;
use JSON::XS;
use centreon::plugins::misc qw(empty);
sub new {
my ($class, %options) = @_;
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();
}
my $self = {};
bless $self, $class;
$options{options}->add_options(arguments => {
'hostname:s' => { name => 'hostname' },
'port:s' => { name => 'port', default => 443 },
'proto:s' => { name => 'proto', default => 'https' },
'timeout:s' => { name => 'timeout' },
'username:s' => { name => 'username' },
'password:s' => { name => 'password' },
'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, default_backend => 'curl');
return $self;
}
sub set_options {
my ($self, %options) = @_;
$self->{option_results} = $options{option_results};
}
sub set_defaults {}
# hostname,username and password are required options
sub check_options {
my ($self, %options) = @_;
$self->{http}->set_options(%{$self->{option_results}});
$self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 50;
if (centreon::plugins::misc::is_empty($self->{option_results}->{hostname})) {
$self->{output}->add_option_msg(short_msg => 'Please set hostname option');
$self->{output}->option_exit();
}
if (centreon::plugins::misc::is_empty($self->{option_results}->{username})) {
$self->{output}->add_option_msg(short_msg => 'Please set username option to authenticate against datacore rest api');
$self->{output}->option_exit();
}
if (centreon::plugins::misc::is_empty($self->{option_results}->{password})) {
$self->{output}->add_option_msg(short_msg => 'Please set password option to authenticate against datacore rest api');
$self->{output}->option_exit();
}
}
sub settings {
my ($self, %options) = @_;
return if (defined($self->{settings_done}));
$self->{http}->add_header(key => 'ServerHost', value => $self->{option_results}->{hostname});
$self->{http}->set_options(basic => 1, credentials => 1);
$self->{settings_done} = 1;
}
# wrapper around centreon::plugins::http::request to add authentication and decode json.
# output : deserialized json from the api if not error found in http call.
sub request_api {
my ($self, %options) = @_;
# datacore api require a ServerHost header with the hostname used to query the api to respond.
# authentication is http standard basic auth.
my $result = $self->{http}->request(
username => $self->{option_results}->{username},
password => $self->{option_results}->{password},
unknown_status => $self->{option_results}->{unknown_http_status},
warning_status => $self->{option_results}->{warning_http_status},
critical_status => $self->{option_results}->{critical_http_status},
%options,
);
# Declare a scalar to deserialize the JSON content string into a perl data structure
my $decoded_content;
eval {
$decoded_content = JSON::XS->new->decode($result);
};
# Catch the error that may arise in case the data received is not JSON
if ($@) {
$self->{output}->add_option_msg(short_msg => "Cannot decode JSON result");
$self->{output}->option_exit();
}
return $decoded_content;
}
1;
__END__
=head1 NAME
Datacore Sansymphony Rest API
=head1 REST API OPTIONS
Datacore Sansymphony Rest API
=over 8
=item B<--hostname>
Address of the Datacore server that hosts the API endpoint.
=item B<--port>
Port of the resource to connect to (default: 443).
=item B<--proto>
HTTP protocol, either http or https (default: 'https')
=item B<--username>
Username to access the endpoint.
=item B<--password>
Password to access the endpoint.
=item B<--timeout>
Set timeout in seconds (default: 10).
=back
=head1 DESCRIPTION
B<custom>.

View File

@ -0,0 +1,174 @@
#
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package storage::datacore::restapi::mode::alerts;
use strict;
use warnings;
use centreon::plugins::misc qw(empty);
use base qw(centreon::plugins::templates::counter);
my %alerts_level = ('trace' => 0, 'info' => 1, 'warning' => 2, 'error' => 3);
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'alerts', type => 0},
];
$self->{maps_counters}->{alerts} = [
{
label => 'error',
nlabel => 'datacore.event.error.count',
set => {
key_values => [ { name => 'error' } ],
output_template => 'number of error alerts : %s',
perfdatas => [ { template => '%d', min => 0 } ]
}
}, {
label => 'warning',
nlabel => 'datacore.alerts.warning.count',
set => {
key_values => [ { name => 'warning' } ],
output_template => 'number of warning alerts : %s',
perfdatas => [ { template => '%d', min => 0 } ]
}
}, {
label => 'info',
nlabel => 'datacore.alerts.info.count',
set => {
key_values => [ { name => 'info' } ],
output_template => 'number of info alerts : %s',
perfdatas => [ { template => '%d', min => 0 } ]
}
}, {
label => 'trace',
nlabel => 'datacore.alerts.trace.count',
set => {
key_values => [ { name => 'trace' } ],
output_template => 'number of trace alerts : %s',
perfdatas => [ { template => '%d', min => 0 } ]
}
},
];
}
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:s' => { name => 'filter_server' },
'max-alert-age:s' => { name => 'max_alert_age' } });
$self->{output} = $options{output};
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
}
sub manage_selection {
my ($self, %options) = @_;
my $alerts = $options{custom}->request_api(
url_path => '/RestService/rest.svc/1.0/alerts'
);
my %alerts_count = (
0 => { count => 0, list => [] },
1 => { count => 0, list => [] },
2 => { count => 0, list => [] },
3 => { count => 0, list => [] });
for my $alert (@$alerts) {
# spec require to filter on time of the log.
$alert->{TimeStamp} =~ /\/Date\((\d+)\)\/$/;
my $alert_date = $1;
if (centreon::plugins::misc::is_empty($alert_date) or $alert_date !~ /^[0-9]*[.,]?\d*$/){
$self->{output}->output_add(long_msg => "alert on $alert->{MachineName} have an invalid date : $alert->{TimeStamp}\n", debug => 1);
next;
}
# filter on age of the alert with a user defined max age
next if (defined($self->{option_results}->{max_alert_age})
and $alert_date < (time - $self->{option_results}->{max_alert_age}) * 1000);
# filter on the machine issuing the alert with a user defined regex
if (!centreon::plugins::misc::is_empty($self->{option_results}->{filter_server})
and $alert->{MachineName} !~ $self->{option_results}->{filter_server}) {
$self->{output}->output_add(long_msg => "excluding alert from machine $alert->{MachineName}\n", debug => 1);
next;
}
$alerts_count{$alert->{Level}}->{count}++;
# we don't want to clog the long output, so we keep only the few first logs.
# we use a array instead of directly adding to long_output because we need to sort errors
if (scalar(@{$alerts_count{$alert->{Level}}->{list}}) < 50) {
push(@{$alerts_count{$alert->{Level}}->{list}}, $alert->{MessageText})
}
}
$self->{output}->output_add(long_msg => "error : " . join("\n", @{$alerts_count{$alerts_level{error}}->{list}}));
$self->{output}->output_add(long_msg => "warning : " . join("\n", @{$alerts_count{$alerts_level{warning}}->{list}}));
$self->{alerts} = {
trace => $alerts_count{$alerts_level{trace}}->{count},
info => $alerts_count{$alerts_level{info}}->{count},
warning => $alerts_count{$alerts_level{warning}}->{count},
error => $alerts_count{$alerts_level{error}}->{count},
};
}
1;
__END__
=head1 MODE
Check Datacore alerts number exposed through the rest api
=over 8
=item B<--max-alert-age>
filter alerts to check those newer than this parameter (s)
=item B<--filter-server>
Define which devices should be monitored based on the MachineName. This option will be treated as a regular expression.
By default all machine will be checked.
=item B<--warning/critical-*>
Warning and critical threshold on the number of alerts of a type before changing state.
Replace * with trace, alert, warning, or error.
=back

View File

@ -0,0 +1,115 @@
#
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package storage::datacore::restapi::mode::listpool;
use strict;
use warnings;
use base qw(centreon::plugins::mode);
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$options{options}->add_options(arguments => {
'filter-name:s' => { name => 'filter_name' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
}
sub manage_selection {
my ($self, %options) = @_;
$self->{pools} = ();
my $pool_list = $options{custom}->request_api(
url_path => '/RestService/rest.svc/1.0/pools');
if (scalar(@$pool_list) == 0) {
$self->{output}->add_option_msg(short_msg => "No pool found in api response.");
$self->{output}->option_exit();
}
for my $pool (@$pool_list) {
next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne ''
&& $pool->{Alias} !~ /$self->{option_results}->{filter_name}/);
push(@{$self->{pools}}, {
ExtendedCaption => $pool->{ExtendedCaption},
Caption => $pool->{Caption},
Id => $pool->{Id},
Alias => $pool->{Alias}}
);
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
if (scalar $self->{pools} == 0) {
$self->{output}->add_option_msg(short_msg => "No pool found.");
$self->{output}->option_exit();
}
foreach (sort @{$self->{pools}}) {
$self->{output}->output_add(long_msg => sprintf("[ExtendedCaption = %s] [Caption = %s] [Id = %s] [Alias = %s]",
$_->{ExtendedCaption}, $_->{Caption}, $_->{Id}, $_->{Alias}));
}
$self->{output}->output_add(
severity => 'OK',
short_msg => 'List pools : '
);
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
sub disco_format {
my ($self, %options) = @_;
$self->{output}->add_disco_format(elements => ['ExtendedCaption', 'Caption', 'Id', 'Alias']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach (sort @{$self->{pools}}) {
$self->{output}->add_disco_entry(ExtendedCaption => $_->{ExtendedCaption}, Caption => $_->{Caption},
Id => $_->{Id}, Id => $_->{Id}, Alias => $_->{Alias});
}
}
1;
=head1 MODE
List pools.
=over 8
=item B<--filter-name>
Filter pool name (can be a regexp).
=back
=cut

View File

@ -0,0 +1,148 @@
#
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package storage::datacore::restapi::mode::monitorstatus;
use strict;
use warnings;
use base qw(centreon::plugins::templates::counter);
use JSON::XS;
use Digest::MD5 qw(md5_hex);
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
use centreon::plugins::misc qw(empty);
my %monitor_state = (1 => "Undefined", 2 => "Healthy", 4 => "Attention", 8 => "Warning", 16 => "Critical");
sub custom_status_output {
my ($self, %options) = @_;
my $res = sprintf(
"'%s' status : '%s', message is '%s'",
$self->{result_values}->{extendedcaption},
$self->{result_values}->{state},
$self->{result_values}->{messagetext}
);
return $res;
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'global', type => 1, message_multiple => 'All memory usages are ok', skipped_code => { -10 => 1 } }
];
$self->{maps_counters}->{global} = [
{ label => 'state',
type => 2,
warning_default => '%{state} =~ /Warning/i',
critical_default => '%{state} =~ /Critical/i',
set => {
key_values => [ { name => 'state' }, { name => 'extendedcaption' }, { name => 'messagetext' } ],
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-caption:s' => { name => 'filter_caption' } });
$self->{cache} = centreon::plugins::statefile->new(%options);
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->{cache}->check_options(option_results => $self->{option_results});
}
sub manage_selection {
my ($self, %options) = @_;
if ($self->{cache}->read('statefile' => 'datacore_api_monitors' . md5_hex($self->{option_results}->{hostname} . $self->{option_results}->{username}))
and $self->{cache}->get(name => 'expires_on') > time() + 1) {
return $self->{cache}->get(name => 'monitor_data');
}
my $monitor_data = $options{custom}->request_api(
url_path => '/RestService/rest.svc/1.0/monitors');
my $datas = { last_timestamp => time(), monitor_data => $monitor_data, expires_on => time() + 60 };
$self->{cache}->write(data => $datas);
my $monitored_count = 0;
for my $object (@$monitor_data) {
if (!centreon::plugins::misc::is_empty($self->{option_results}->{filter_caption})
and $object->{ExtendedCaption} !~ $self->{option_results}->{filter_caption}) {
next;
}
$self->{global}->{$monitored_count} = {
state => $monitor_state{$object->{State}},
messagetext => $object->{MessageText},
extendedcaption => $object->{ExtendedCaption}
};
$monitored_count++;
}
# for now if no data is given to the counter, output is OK: with status ok, instead of unknown.
# We manage this case in each plugin for now.
if ($monitored_count == 0) {
$self->{output}->add_option_msg(short_msg => 'No monitors where checked, please check filter_caption parameter and api response.');
$self->{output}->option_exit();
}
}
# as --filter-caption allow to filter element to check and this api don't allow parameter filtering, we should cache
# the output in case a client make multiples check a minute.
1;
__END__
=head1 MODE
Check Datacore monitor status exposed through the rest api.
=over 8
=item B<--filter-caption>
Define which element should be monitored based on the extended caption. This option will be treated as a regular expression.
By default all elements will be checked.
=item B<--warning-state> B<--critical-state>
define which output from the api should be considered warning or critical.
warning_default = '%{state} =~ /Warning/i',
critical_default = '%{state} =~ /Critical/i',
possible value for state : Undefined, Healthy, Attention, Warning, Critical.
=back

View File

@ -0,0 +1,121 @@
#
# Copyright 2024 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package storage::datacore::restapi::mode::poolspaceusage;
use strict;
use warnings;
use base qw(centreon::plugins::templates::counter);
use JSON::XS;
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
# BytesAllocatedPercentage is the disk usage of the pool
# in datacore you can make thin provisionning, where you give to each partition more than what you really have.
# oversubscribed is the number of Bytes allocated minus the number of bytes present in the system.
{ name => 'BytesAllocatedPercentage', type => 0 },
{ name => 'oversubscribed', type => 0 },
];
$self->{maps_counters}->{BytesAllocatedPercentage} = [
{
label => 'bytesallocatedpercentage',
nlabel => 'datacore.pool.bytesallocated.percentage',
set => {
key_values => [ { name => 'bytesallocatedpercentage' } ],
output_template => 'Bytes Allocated : %s %%',
perfdatas => [
{ template => '%d', unit => '%', min => 0, max => 100 }
]
}
} ];
$self->{maps_counters}->{oversubscribed} = [ {
label => 'oversubscribed',
nlabel => 'datacore.pool.oversubscribed.bytes',
set => {
key_values => [ { name => 'oversubscribed' } ],
output_template => 'Over subscribed bytes : %s',
perfdatas => [
{ template => '%d', unit => 'bytes', min => 0 }
]
}
} ];
}
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 => {
'pool-id:s' => { name => 'pool_id' } });
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
if (centreon::plugins::misc::is_empty($self->{option_results}->{pool_id})) {
$self->{output}->add_option_msg(short_msg => 'Please set pool-id option');
$self->{output}->option_exit();
}
}
sub manage_selection {
my ($self, %options) = @_;
my $data = $options{custom}->request_api(
url_path => '/RestService/rest.svc/1.0/performances/' . $self->{option_results}->{pool_id},
);
if (defined($data->[1])) {
$self->{output}->add_option_msg(short_msg => 'multiples pools found in api response, only one is expected. Please check pool_id and datacore versions.');
$self->{output}->option_exit();
}
$self->{BytesAllocatedPercentage}->{bytesallocatedpercentage} = $data->[0]->{"BytesAllocatedPercentage"};
$self->{oversubscribed}->{oversubscribed} = $data->[0]->{"BytesOverSubscribed"};
}
1;
__END__
=head1 MODE
Check Datacore pool space and over subscribed usage exposed through the rest api.
=over 8
=item B<--pool-id>
Id of the pool to check. See list-pool autodiscovery mode to list pools id (required).
=item B<--warning-oversubscribed> B<--critical-oversubscribed>
Warning and critical threshold on the number of Bytes suscribed over the real space of the pool.
=item B<--warning-bytesallocatedpercentage> B<--critical-bytesallocatedpercentage>
Warning and critical threshold on the percentage of bytes allocated in the pool.
=back

View File

@ -0,0 +1,27 @@
package storage::datacore::restapi::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;
# A version, we don't really use it but could help if your want to version your code
$self->{version} = '0.1';
$self->{modes} = {
'pool-usage' => 'storage::datacore::restapi::mode::poolspaceusage',
'alerts' => 'storage::datacore::restapi::mode::alerts',
'list-pool' => 'storage::datacore::restapi::mode::listpool',
'status-monitor' => 'storage::datacore::restapi::mode::monitorstatus',
};
$self->{custom_modes}->{api} = 'storage::datacore::restapi::custom::api';
return $self;
}
1;
=head1 PLUGIN DESCRIPTION
Check Datacore using rest API.

View File

@ -153,6 +153,7 @@ AWS CloudTrail check trail status
FOR ${checktrailstatus_value} IN @{checktrailstatus_values}
${output} Run
... ${CMD} --mode=checktrailstatus --endpoint=http://localhost:3000/cloudtrail/gettrailstatus/${checktrailstatus_value.trailstatus} --trail-name=${checktrailstatus_value.trailname}
${output} Strip String ${output}
Should Be Equal As Strings
... ${output}
... ${checktrailstatus_value.result}
@ -188,6 +189,7 @@ AWS CloudTrail count events
${command} Catenate ${command} --critical-count=${countevents_value.criticalcount}
END
${output} Run ${command}
${output} Strip String ${output}
Should Be Equal As Strings
... ${output}
... ${countevents_value.result}
@ -204,13 +206,7 @@ Start Mockoon
... ${MOCKOON_JSON}
... --port
... 3000
... --pname
... aws-cloudtrail
Wait For Process ${process}
Sleep 5s
Stop Mockoon
${process} Start Process
... mockoon-cli
... stop
... mockoon-aws-cloudtrail
Wait For Process ${process}
Terminate All Processes

View File

@ -14,29 +14,29 @@ Test Timeout 120s
${CENTREON_PLUGINS} ${CURDIR}${/}..${/}..${/}..${/}src${/}centreon_plugins.pl
${MOCKOON_JSON} ${CURDIR}${/}..${/}..${/}resources${/}mockoon${/}cloud-azure-policyinsights-policystates.json
${LOGIN_ENDPOINT} http://localhost:3000/login
${LOGIN_ENDPOINT} http://localhost:3001/login
${CMD} perl ${CENTREON_PLUGINS} --plugin=cloud::azure::policyinsights::policystates::plugin --subscription=subscription --tenant=tenant --client-id=client_id --client-secret=secret --login-endpoint=${LOGIN_ENDPOINT}
&{compliance_value1}
... endpoint=http://localhost:3000/ok
... endpoint=http://localhost:3001/ok
... policyname=
... resourcelocation=
... resourcetype=
... result=OK: Number of non compliant policies: 0 - All compliances states are ok | 'policies.non_compliant.count'=0;;;0;
&{compliance_value2}
... endpoint=http://localhost:3000/oknextlink
... endpoint=http://localhost:3001/oknextlink
... policyname=9daedab3-fb2d-461e-b861-71790eead4f6
... resourcelocation=
... resourcetype=
... result=OK: Number of non compliant policies: 0 - All compliances states are ok | 'policies.non_compliant.count'=0;;;0;
&{compliance_value3}
... endpoint=http://localhost:3000/nok1
... endpoint=http://localhost:3001/nok1
... policyname=9daedab3-fb2d-461e-b861-71790eead4f6
... resourcelocation=fr
... resourcetype=
... result=CRITICAL: Compliance state for policy '9daedab3-fb2d-461e-b861-71790eead4f6' on resource 'mypubip1' is 'NonCompliant' | 'policies.non_compliant.count'=1;;;0;
&{compliance_value4}
... endpoint=http://localhost:3000/nok2
... endpoint=http://localhost:3001/nok2
... policyname=9daedab3-fb2d-461e-b861-71790eead4f6
... resourcelocation=fr
... resourcetype=ip
@ -66,6 +66,7 @@ Azure PolicyInsights PolicyStates compliance
${command} Catenate ${command} --resource-type=${compliance_value.resourcetype}
END
${output} Run ${command}
${output} Strip String ${output}
Should Be Equal As Strings
... ${output}
... ${compliance_value.result}
@ -82,13 +83,7 @@ Start Mockoon
... ${MOCKOON_JSON}
... --port
... 3000
... --pname
... azure-policyinsights
Wait For Process ${process}
Sleep 5s
Stop Mockoon
${process} Start Process
... mockoon-cli
... stop
... mockoon-azure-policyinsights
Wait For Process ${process}
Terminate All Processes

View File

@ -0,0 +1,77 @@
*** Settings ***
Documentation datacore rest api plugin
Library Examples
Library OperatingSystem
Library Process
Library String
Suite Setup Start Mockoon
Suite Teardown Stop Mockoon
Test Timeout 120s
*** Variables ***
${CENTREON_PLUGINS} ${CURDIR}${/}..${/}..${/}..${/}src${/}centreon_plugins.pl
${MOCKOON_JSON} ${CURDIR}${/}..${/}..${/}resources${/}mockoon${/}storage-datacore-restapi.json
${CMD} perl ${CENTREON_PLUGINS} --plugin=storage::datacore::restapi::plugin --password=pass --username=user --port=3000 --hostname=127.0.0.1 --proto=http
*** Test Cases ***
Datacore check pool usage
[Documentation] Check Datacore pool usage
[Tags] storage api
${output} Run
... ${CMD} --mode=pool-usage --critical-oversubscribed=${critical-oversubscribed} --warning-oversubscribed=${warning-oversubscribed} --warning-bytesallocatedpercentage=${warning-bytesallocatedpercentage} --critical-bytesallocatedpercentage=${critical-bytesallocatedpercentage} --pool-id=B5C140F5-6B13-4CAD-AF9D-F7C4172B3A1D:{4dec1b5a-2577-11e5-80c3-00155d651622}
${output} Strip String ${output}
Should Be Equal As Strings
... ${output}
... ${result}
... Wrong output result for pool usage :\n\n ${output} \n\n ${result}\n\n
Examples: warning-bytesallocatedpercentage critical-bytesallocatedpercentage warning-oversubscribed critical-oversubscribed result --
... 2 5 -1 3 CRITICAL: Bytes Allocated : 12 % WARNING: Over subscribed bytes : 0 | 'datacore.pool.bytesallocated.percentage'=12%;0:2;0:5;0;100 'datacore.pool.oversubscribed.bytes'=0bytes;0:-1;0:3;0;
... 70 80 10 20 OK: Bytes Allocated : 12 % - Over subscribed bytes : 0 | 'datacore.pool.bytesallocated.percentage'=12%;0:70;0:80;0;100 'datacore.pool.oversubscribed.bytes'=0bytes;0:10;0:20;0;
Datacore check alert count
[Documentation] Check Datacore pool usage
[Tags] storage api
${output} Run
... ${CMD} --mode=alerts --warning-error=${warning-error} --critical-error=${critical-error} --warning-warning=${warning-warning} --critical-warning=${critical-warning}
${output} Strip String ${output}
Should Be Equal As Strings
... ${output}
... ${result}
... Wrong output result for alert count :\n\n ${output} \n\n ${result}\n\n
Examples: warning-error critical-error warning-warning critical-warning result --
... 0 1 5 5 WARNING: number of error alerts : 1 | 'datacore.event.error.count'=1;0:0;0:1;0; 'datacore.alerts.warning.count'=1;0:5;0:5;0; 'datacore.alerts.info.count'=0;;;0; 'datacore.alerts.trace.count'=0;;;0;
... 5 5 5 5 OK: number of error alerts : 1, number of warning alerts : 1, number of info alerts : 0, number of trace alerts : 0 | 'datacore.event.error.count'=1;0:5;0:5;0; 'datacore.alerts.warning.count'=1;0:5;0:5;0; 'datacore.alerts.info.count'=0;;;0; 'datacore.alerts.trace.count'=0;;;0;
Datacore check status monitor
[Documentation] Check Datacore pool usage
[Tags] storage api
${output} Run
... ${CMD} --mode=status-monitor
${output} Strip String ${output}
Should Be Equal As Strings
... ${output}
... ${result}
... Wrong output result for status monitor :\n${output} \nresult:\n${result}\n\n
Examples: result --
... CRITICAL: 'State of HostVM2' status : 'Critical', message is 'Connected'
*** Keywords ***
Start Mockoon
${process} Start Process
... mockoon-cli
... start
... --data
... ${MOCKOON_JSON}
... --port
... 3000
Sleep 5s
Stop Mockoon
Terminate All Processes

View File

@ -0,0 +1,174 @@
{
"uuid": "317849df-2152-4b89-88f7-f22ea37aab32",
"lastMigration": 27,
"name": "Storage datacore api",
"endpointPrefix": "",
"latency": 0,
"port": 3000,
"hostname": "",
"folders": [],
"routes": [
{
"uuid": "9d203639-fb39-402b-9759-91c156e247c6",
"type": "http",
"documentation": "",
"method": "get",
"endpoint": "RestService/rest.svc/1.0/pools",
"responses": [
{
"uuid": "f8d1590b-878f-4884-9214-dea80580eb75",
"body": "[{\r\n \"Caption\" : \"Disk pool 1\",\r\n \"ExtendedCaption\" : \"Disk pool 1 on StorageSvr001\",\r\n \"Id\" : \"A3E78CFA-DBEC-44E1-A23C-E9E262EC4551:{d68b8a36-0ec4-11e5-80ba-00155d651622}\",\r\n \"Internal\" : false,\r\n \"SequenceNumber\" : 11963,\r\n \"Alias\" : \"Disk pool 1\",\r\n \"AutoTieringEnabled\" : true,\r\n \"ChunkSize\" : {\r\n \"Value\" : 134217728\r\n },\r\n \"Description\" : null,\r\n \"InSharedMode\" : false,\r\n \"IsAuthorized\" : true,\r\n \"MaxTierNumber\" : 3,\r\n \"PoolMode\" : 1,\r\n \"PoolStatus\" : 0,\r\n \"PresenceStatus\" : 1,\r\n \"SMPAApproved\" : false,\r\n \"ServerId\" : \"A3E78CFA-DBEC-44E1-A23C-E9E262EC4551\",\r\n \"SharedPoolId\" : null,\r\n \"TierReservedPct\" : 0,\r\n \"Type\" : 0,\r\n \"IsBulk\" : false\r\n},\r\n{\r\n \"Caption\" : \"Shared pool 1\",\r\n \"ExtendedCaption\" : \"Shared pool 1 on StorageSvr002\",\r\n \"Id\" : \"B5C140F5-6B13-4CAD-AF9D-F7C4172B3A1D:{4dec1b5a-2577-11e5-80c3-00155d651622}\",\r\n \"Internal\" : false,\r\n \"SequenceNumber\" : 11967,\r\n \"Alias\" : \"Shared pool 1\",\r\n \"AutoTieringEnabled\" : true,\r\n \"ChunkSize\" : {\r\n \"Value\" : 134217728\r\n },\r\n \"Description\" : null,\r\n \"InSharedMode\" : true,\r\n \"IsAuthorized\" : true,\r\n \"MaxTierNumber\" : 3,\r\n \"PoolMode\" : 1,\r\n \"PoolStatus\" : 0,\r\n \"PresenceStatus\" : 1,\r\n \"SMPAApproved\" : true,\r\n \"ServerId\" : \"B5C140F5-6B13-4CAD-AF9D-F7C4172B3A1D\",\r\n \"SharedPoolId\" : \"{4dec1b5a-2577-11e5-80c3-00155d651622}\",\r\n \"TierReservedPct\" : 0,\r\n \"Type\" : 0,\r\n \"IsBulk\" : false\r\n} ]",
"latency": 0,
"statusCode": 200,
"label": "",
"headers": [],
"bodyType": "INLINE",
"filePath": "",
"databucketID": "",
"sendFileAsBody": false,
"rules": [],
"rulesOperator": "OR",
"disableTemplating": false,
"fallbackTo404": false,
"default": true
}
],
"enabled": true,
"responseMode": null
},
{
"uuid": "8837f5cd-5ca3-4779-ba8e-6b46692c487b",
"type": "http",
"documentation": "",
"method": "get",
"endpoint": "RestService/rest.svc/1.0/performances/B5C140F5-6B13-4CAD-AF9D-F7C4172B3A1D:%7B4dec1b5a-2577-11e5-80c3-00155d651622%7D",
"responses": [
{
"uuid": "a5bf53e2-5edf-437e-a684-68315cfa7824",
"body": "[\n {\n \"CollectionTime\": \"/Date(1486402608775)/\",\n \"NullCounterMap\": 0,\n \"BytesAllocated\": 6174015488,\n \"BytesAllocatedPercentage\": 12,\n \"BytesAvailable\": 47110422528,\n \"BytesAvailablePercentage\": 88,\n \"BytesInReclamation\": 0,\n \"BytesInReclamationPercentage\": 0,\n \"BytesOverSubscribed\": 0,\n \"BytesReserved\": 0,\n \"BytesReservedPercentage\": 0,\n \"BytesTotal\": 53284438016,\n \"EstimatedDepletionTime\": 2592000001,\n \"MaxPoolBytes\": 1108127332171776,\n \"MaxReadTime\" : 0,\n \"MaxReadWriteTime\" : 0,\n \"MaxWriteTime\" : 0,\n \"PercentAllocated\" : 12,\n \"PercentAvailable\" : 88,\n \"TotalBytesMigrated\" : 0,\n \"TotalBytesRead\" : 307200,\n \"TotalBytesTransferred\" : 2036756992,\n \"TotalBytesWritten\" : 2036470272,\n \"TotalOperations\" : 53002,\n \"TotalReadTime\" : 0,\n \"TotalReads\" : 18,\n \"TotalWriteTime\" : 74994,\n \"TotalWrites\" : 52998\n }\n]",
"latency": 0,
"statusCode": 200,
"label": "",
"headers": [],
"bodyType": "INLINE",
"filePath": "",
"databucketID": "",
"sendFileAsBody": false,
"rules": [],
"rulesOperator": "OR",
"disableTemplating": false,
"fallbackTo404": false,
"default": true
}
],
"enabled": true,
"responseMode": null
},
{
"uuid": "ce9e85c8-c72e-47d4-b70a-0fd3c3a6d703",
"type": "http",
"documentation": "",
"method": "get",
"endpoint": "RestService/rest.svc/1.0/alerts",
"responses": [
{
"uuid": "b6425c83-2f13-4ffe-a9f6-c73feb54c2ec",
"body": "[ {\n \"Caller\" : \"ServerMachineGroup.UpdateServers\",\n \"HighPriority\" : true,\n \"Id\" : {\n \"MachineId\" : \"A3E78CFA-DBEC-44E1-A23C-E9E262EC4551\",\n \"SequenceNumber\" : 34937\n },\n \"Level\" : 2,\n \"MachineName\" : \"STORAGESVR001\",\n \"MessageData\" : [ \"StorageSvr002\" ],\n \"MessageText\" : \"Connection to server {0} has been lost.\",\n \"NeedsAcknowledge\" : false,\n \"Sources\" : [ {\n \"SourceCaption\" : \"Group1\",\n \"SourceId\" : \"4b428832-fd51-45df-9c21-ce267e1ceb7a\",\n \"SourceType\" : 12\n } ],\n \"TimeStamp\" : \"/Date(1437398005546)/\",\n \"UserId\" : null,\n \"UserName\" : null,\n \"Visibility\" : 64\n}, {\n \"Caller\" : \"BasePerfMonitor`1.SetState\",\n \"HighPriority\" : true,\n \"Id\" : {\n \"MachineId\" : \"A3E78CFA-DBEC-44E1-A23C-E9E262EC4551\",\n \"SequenceNumber\" : 33985\n },\n \"Level\" : 3,\n \"MachineName\" : \"STORAGESVR001\",\n \"MessageData\" : null,\n \"MessageText\" : \"The Replication buffer free space of StorageSvr001 in Group1 is <= 10%\",\n \"NeedsAcknowledge\" : false,\n \"Sources\" : [ {\n \"SourceCaption\" : \"Replication buffer free space of StorageSvr001 in Group1\",\n \"SourceId\" : \"FallingThresholdPerfMonitor`1<A3E78CFA-DBEC-44E1-A23C-E9E262EC4551>ReplicationBufferPercentFreeSpace\",\n \"SourceType\" : 3\n }, {\n \"SourceCaption\" : \"StorageSvr001 in Group1\",\n \"SourceId\" : \"A3E78CFA-DBEC-44E1-A23C-E9E262EC4551\",\n \"SourceType\" : 12\n }, {\n \"SourceCaption\" : \"Group1\",\n \"SourceId\" : \"4b428832-fd51-45df-9c21-ce267e1ceb7a\",\n \"SourceType\" : 12\n } ],\n \"TimeStamp\" : \"/Date(1437397587894)/\",\n \"UserId\" : null,\n \"UserName\" : null,\n \"Visibility\" : 64\n}]",
"latency": 0,
"statusCode": 200,
"label": "",
"headers": [],
"bodyType": "INLINE",
"filePath": "",
"databucketID": "",
"sendFileAsBody": false,
"rules": [],
"rulesOperator": "OR",
"disableTemplating": false,
"fallbackTo404": false,
"default": true
}
],
"enabled": true,
"responseMode": null
},
{
"uuid": "a916f10f-b2f2-498a-9b87-3aeffd80c8dc",
"type": "http",
"documentation": "",
"method": "get",
"endpoint": "RestService/rest.svc/1.0/monitors",
"responses": [
{
"uuid": "d2713bdd-33e9-415a-bffe-16e279b1b753",
"body": "[\n {\n \"Caption\": \"State\",\n \"ExtendedCaption\": \"State of HostVM2\",\n \"Id\": \"ClientMachineStateMonitor<ed89ef91d72142dc958e02c5b7014fac>\",\n \"Internal\": false,\n \"SequenceNumber\": 9417,\n \"Description\": \"Monitors the state of hosts.\",\n \"MessageText\": \"Connected\",\n \"MonitoredObjectId\": \"ed89ef91d72142dc958e02c5b7014fac\",\n \"State\": 16,\n \"TemplateId\": \"T(DataCore.Executive.Controller.ClientMachineStateMonitor<DataCore.Executive.Controller.ClientMachine>)\",\n \"TimeStamp\": \"/Date(1486136115475-0500)/\"\n },\n {\n \"Caption\": \"I/O latency\",\n \"ExtendedCaption\": \"I/O latency of Mirror of Virtual disk 1 on StorageSvr005\",\n \"Id\": \"RisingThresholdPerfMonitor`1<V.{2f652562-e7e3-11e6-80d7-00155d651611}-00000001_N.22690030D9218568>TotalOperationsTime\",\n \"Internal\": false,\n \"SequenceNumber\": 10036,\n \"Description\": \"Monitors the physical disks latency.\",\n \"MessageText\": \"Disabled\",\n \"MonitoredObjectId\": \"V.{2f652562-e7e3-11e6-80d7-00155d651611}-00000001_N.22690030D9218568\",\n \"State\": 1,\n \"TemplateId\": \"T(DataCore.Executive.Controller.RisingThresholdPerfMonitor`1[T]<V.{2f652562-e7e3-11e6-80d7-00155d651611}-00000001_N.22690030D9218568>TotalOperationsTime)\",\n \"TimeStamp\": \"/Date(1486148705910-0500)/\"\n }\n]",
"latency": 0,
"statusCode": 200,
"label": "",
"headers": [],
"bodyType": "INLINE",
"filePath": "",
"databucketID": "",
"sendFileAsBody": false,
"rules": [],
"rulesOperator": "OR",
"disableTemplating": false,
"fallbackTo404": false,
"default": true
}
],
"enabled": true,
"responseMode": null
}
],
"rootChildren": [
{
"type": "route",
"uuid": "9d203639-fb39-402b-9759-91c156e247c6"
},
{
"type": "route",
"uuid": "8837f5cd-5ca3-4779-ba8e-6b46692c487b"
},
{
"type": "route",
"uuid": "ce9e85c8-c72e-47d4-b70a-0fd3c3a6d703"
},
{
"type": "route",
"uuid": "a916f10f-b2f2-498a-9b87-3aeffd80c8dc"
}
],
"proxyMode": false,
"proxyHost": "",
"proxyRemovePrefix": false,
"tlsOptions": {
"enabled": false,
"type": "CERT",
"pfxPath": "",
"certPath": "",
"keyPath": "",
"caPath": "",
"passphrase": ""
},
"cors": true,
"headers": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"proxyReqHeaders": [
{
"key": "",
"value": ""
}
],
"proxyResHeaders": [
{
"key": "",
"value": ""
}
],
"data": []
}

View File

@ -0,0 +1,179 @@
{
"uuid": "8cba072c-7794-4ff7-ab36-158ef1abed39",
"lastMigration": 32,
"name": "Storage datacore api",
"endpointPrefix": "",
"latency": 0,
"port": 3001,
"hostname": "",
"folders": [],
"routes": [
{
"uuid": "148371c5-aaa7-4bf0-a818-e81a21aa7f9a",
"type": "http",
"documentation": "",
"method": "get",
"endpoint": "RestService/rest.svc/1.0/pools",
"responses": [
{
"uuid": "003eae6e-f58f-44db-bd03-3b44ca578046",
"body": "[ {\n \"Caption\" : \"Disk pool 1\",\n \"ExtendedCaption\" : \"Disk pool 1 on StorageSvr001\",\n \"Id\" : \"A3E78CFA-DBEC-44E1-A23C-E9E262EC4551:{d68b8a36-0ec4-11e5-80ba-00155d651622}\",\n \"Internal\" : false,\n \"SequenceNumber\" : 11963,\n \"Alias\" : \"Disk pool 1\",\n \"AutoTieringEnabled\" : true,\n \"ChunkSize\" : {\n \"Value\" : 134217728\n },\n \"Description\" : null,\n \"InSharedMode\" : false,\n \"IsAuthorized\" : true,\n \"MaxTierNumber\" : 3,\n \"PoolMode\" : 1,\n \"PoolStatus\" : 0,\n \"PresenceStatus\" : 1,\n \"SMPAApproved\" : false,\n \"ServerId\" : \"A3E78CFA-DBEC-44E1-A23C-E9E262EC4551\",\n \"SharedPoolId\" : null,\n \"TierReservedPct\" : 0,\n \"Type\" : 0,\n \"IsBulk\" : false\n},\n{\n \"Caption\" : \"Shared pool 1\",\n \"ExtendedCaption\" : \"Shared pool 1 on StorageSvr002\",\n \"Id\" : \"B5C140F5-6B13-4CAD-AF9D-F7C4172B3A1D:{4dec1b5a-2577-11e5-80c3-00155d651622}\",\n \"Internal\" : false,\n \"SequenceNumber\" : 11967,\n \"Alias\" : \"Shared pool 1\",\n \"AutoTieringEnabled\" : true,\n \"ChunkSize\" : {\n \"Value\" : 134217728\n },\n \"Description\" : null,\n \"InSharedMode\" : true,\n \"IsAuthorized\" : true,\n \"MaxTierNumber\" : 3,\n \"PoolMode\" : 1,\n \"PoolStatus\" : 0,\n \"PresenceStatus\" : 1,\n \"SMPAApproved\" : true,\n \"ServerId\" : \"B5C140F5-6B13-4CAD-AF9D-F7C4172B3A1D\",\n \"SharedPoolId\" : \"{4dec1b5a-2577-11e5-80c3-00155d651622}\",\n \"TierReservedPct\" : 0,\n \"Type\" : 0,\n \"IsBulk\" : false\n} ]",
"latency": 0,
"statusCode": 200,
"label": "",
"headers": [],
"bodyType": "INLINE",
"filePath": "",
"databucketID": "",
"sendFileAsBody": false,
"rules": [],
"rulesOperator": "OR",
"disableTemplating": false,
"fallbackTo404": false,
"default": true,
"crudKey": "id",
"callbacks": []
}
],
"responseMode": null
},
{
"uuid": "0c038179-3723-4d67-9bed-fc226629c847",
"type": "http",
"documentation": "",
"method": "get",
"endpoint": "RestService/rest.svc/1.0/performances/B5C140F5-6B13-4CAD-AF9D-F7C4172B3A1D:%7B4dec1b5a-2577-11e5-80c3-00155d651622%7D",
"responses": [
{
"uuid": "0eb0a2ca-2f12-40af-ba94-0feef989b6a1",
"body": "[\n {\n \"CollectionTime\": \"/Date(1486402608775)/\",\n \"NullCounterMap\": 0,\n \"BytesAllocated\": 6174015488,\n \"BytesAllocatedPercentage\": 12,\n \"BytesAvailable\": 47110422528,\n \"BytesAvailablePercentage\": 88,\n \"BytesInReclamation\": 0,\n \"BytesInReclamationPercentage\": 0,\n \"BytesOverSubscribed\": 0,\n \"BytesReserved\": 0,\n \"BytesReservedPercentage\": 0,\n \"BytesTotal\": 53284438016,\n \"EstimatedDepletionTime\": 2592000001,\n \"MaxPoolBytes\": 1108127332171776,\n \"MaxReadTime\" : 0,\n \"MaxReadWriteTime\" : 0,\n \"MaxWriteTime\" : 0,\n \"PercentAllocated\" : 12,\n \"PercentAvailable\" : 88,\n \"TotalBytesMigrated\" : 0,\n \"TotalBytesRead\" : 307200,\n \"TotalBytesTransferred\" : 2036756992,\n \"TotalBytesWritten\" : 2036470272,\n \"TotalOperations\" : 53002,\n \"TotalReadTime\" : 0,\n \"TotalReads\" : 18,\n \"TotalWriteTime\" : 74994,\n \"TotalWrites\" : 52998\n }\n]",
"latency": 0,
"statusCode": 200,
"label": "",
"headers": [],
"bodyType": "INLINE",
"filePath": "",
"databucketID": "",
"sendFileAsBody": false,
"rules": [],
"rulesOperator": "OR",
"disableTemplating": false,
"fallbackTo404": false,
"default": true,
"crudKey": "id",
"callbacks": []
}
],
"responseMode": null
},
{
"uuid": "b9f7dd2b-e1e1-4902-95ba-c6b76a1de390",
"type": "http",
"documentation": "",
"method": "get",
"endpoint": "RestService/rest.svc/1.0/alerts",
"responses": [
{
"uuid": "a1dece29-074b-4100-a764-f7ddccdec8da",
"body": "[ {\n \"Caller\" : \"ServerMachineGroup.UpdateServers\",\n \"HighPriority\" : true,\n \"Id\" : {\n \"MachineId\" : \"A3E78CFA-DBEC-44E1-A23C-E9E262EC4551\",\n \"SequenceNumber\" : 34937\n },\n \"Level\" : 2,\n \"MachineName\" : \"STORAGESVR001\",\n \"MessageData\" : [ \"StorageSvr002\" ],\n \"MessageText\" : \"Connection to server {0} has been lost.\",\n \"NeedsAcknowledge\" : false,\n \"Sources\" : [ {\n \"SourceCaption\" : \"Group1\",\n \"SourceId\" : \"4b428832-fd51-45df-9c21-ce267e1ceb7a\",\n \"SourceType\" : 12\n } ],\n \"TimeStamp\" : \"/Date(1437398005546)/\",\n \"UserId\" : null,\n \"UserName\" : null,\n \"Visibility\" : 64\n}, {\n \"Caller\" : \"BasePerfMonitor`1.SetState\",\n \"HighPriority\" : true,\n \"Id\" : {\n \"MachineId\" : \"A3E78CFA-DBEC-44E1-A23C-E9E262EC4551\",\n \"SequenceNumber\" : 33985\n },\n \"Level\" : 3,\n \"MachineName\" : \"STORAGESVR001\",\n \"MessageData\" : null,\n \"MessageText\" : \"The Replication buffer free space of StorageSvr001 in Group1 is <= 10%\",\n \"NeedsAcknowledge\" : false,\n \"Sources\" : [ {\n \"SourceCaption\" : \"Replication buffer free space of StorageSvr001 in Group1\",\n \"SourceId\" : \"FallingThresholdPerfMonitor`1<A3E78CFA-DBEC-44E1-A23C-E9E262EC4551>ReplicationBufferPercentFreeSpace\",\n \"SourceType\" : 3\n }, {\n \"SourceCaption\" : \"StorageSvr001 in Group1\",\n \"SourceId\" : \"A3E78CFA-DBEC-44E1-A23C-E9E262EC4551\",\n \"SourceType\" : 12\n }, {\n \"SourceCaption\" : \"Group1\",\n \"SourceId\" : \"4b428832-fd51-45df-9c21-ce267e1ceb7a\",\n \"SourceType\" : 12\n } ],\n \"TimeStamp\" : \"/Date(1437397587894)/\",\n \"UserId\" : null,\n \"UserName\" : null,\n \"Visibility\" : 64\n}]",
"latency": 0,
"statusCode": 200,
"label": "",
"headers": [],
"bodyType": "INLINE",
"filePath": "",
"databucketID": "",
"sendFileAsBody": false,
"rules": [],
"rulesOperator": "OR",
"disableTemplating": false,
"fallbackTo404": false,
"default": true,
"crudKey": "id",
"callbacks": []
}
],
"responseMode": null
},
{
"uuid": "be0b350e-f8da-4998-a045-a3cf840745c0",
"type": "http",
"documentation": "",
"method": "get",
"endpoint": "RestService/rest.svc/1.0/monitors",
"responses": [
{
"uuid": "6f53cd5e-7417-4fdf-a310-e2a7af4b7c3a",
"body": "[\r\n {\r\n \"Caption\": \"State\",\r\n \"ExtendedCaption\": \"State of HostVM2\",\r\n \"Id\": \"ClientMachineStateMonitor<ed89ef91d72142dc958e02c5b7014fac>\",\r\n \"Internal\": false,\r\n \"SequenceNumber\": 9417,\r\n \"Description\": \"Monitors the state of hosts.\",\r\n \"MessageText\": \"Connected\",\r\n \"MonitoredObjectId\": \"ed89ef91d72142dc958e02c5b7014fac\",\r\n \"State\": 16,\r\n \"TemplateId\": \"T(DataCore.Executive.Controller.ClientMachineStateMonitor<DataCore.Executive.Controller.ClientMachine>)\",\r\n \"TimeStamp\": \"/Date(1486136115475-0500)/\"\r\n },\r\n {\r\n \"Caption\": \"I/O latency\",\r\n \"ExtendedCaption\": \"I/O latency of Mirror of Virtual disk 1 on StorageSvr005\",\r\n \"Id\": \"RisingThresholdPerfMonitor`1<V.{2f652562-e7e3-11e6-80d7-00155d651611}-00000001_N.22690030D9218568>TotalOperationsTime\",\r\n \"Internal\": false,\r\n \"SequenceNumber\": 10036,\r\n \"Description\": \"Monitors the physical disks latency.\",\r\n \"MessageText\": \"Disabled\",\r\n \"MonitoredObjectId\": \"V.{2f652562-e7e3-11e6-80d7-00155d651611}-00000001_N.22690030D9218568\",\r\n \"State\": 1,\r\n \"TemplateId\": \"T(DataCore.Executive.Controller.RisingThresholdPerfMonitor`1[T]<V.{2f652562-e7e3-11e6-80d7-00155d651611}-00000001_N.22690030D9218568>TotalOperationsTime)\",\r\n \"TimeStamp\": \"/Date(1486148705910-0500)/\"\r\n }\r\n]",
"latency": 0,
"statusCode": 200,
"label": "",
"headers": [],
"bodyType": "INLINE",
"filePath": "",
"databucketID": "",
"sendFileAsBody": false,
"rules": [],
"rulesOperator": "OR",
"disableTemplating": false,
"fallbackTo404": false,
"default": true,
"crudKey": "id",
"callbacks": []
}
],
"responseMode": null
}
],
"rootChildren": [
{
"type": "route",
"uuid": "148371c5-aaa7-4bf0-a818-e81a21aa7f9a"
},
{
"type": "route",
"uuid": "0c038179-3723-4d67-9bed-fc226629c847"
},
{
"type": "route",
"uuid": "b9f7dd2b-e1e1-4902-95ba-c6b76a1de390"
},
{
"type": "route",
"uuid": "be0b350e-f8da-4998-a045-a3cf840745c0"
}
],
"proxyMode": false,
"proxyHost": "",
"proxyRemovePrefix": false,
"tlsOptions": {
"enabled": false,
"type": "CERT",
"pfxPath": "",
"certPath": "",
"keyPath": "",
"caPath": "",
"passphrase": ""
},
"cors": true,
"headers": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"proxyReqHeaders": [
{
"key": "",
"value": ""
}
],
"proxyResHeaders": [
{
"key": "",
"value": ""
}
],
"data": [],
"callbacks": []
}