diff --git a/network/cisco/meraki/cloudcontroller/restapi/custom/api.pm b/network/cisco/meraki/cloudcontroller/restapi/custom/api.pm index d26c8885a..e4af020a7 100644 --- a/network/cisco/meraki/cloudcontroller/restapi/custom/api.pm +++ b/network/cisco/meraki/cloudcontroller/restapi/custom/api.pm @@ -43,13 +43,15 @@ sub new { if (!defined($options{noptions})) { $options{options}->add_options(arguments => { - 'hostname:s' => { name => 'hostname' }, - 'port:s' => { name => 'port' }, - 'proto:s' => { name => 'proto' }, - 'api-token:s' => { name => 'api_token' }, - 'timeout:s' => { name => 'timeout' }, - 'reload-cache-time:s' => { name => 'reload_cache_time' }, - 'ignore-permission-errors' => { name => 'ignore_permission_errors' } + 'hostname:s' => { name => 'hostname' }, + 'port:s' => { name => 'port' }, + 'proto:s' => { name => 'proto' }, + 'api-token:s' => { name => 'api_token' }, + 'timeout:s' => { name => 'timeout' }, + 'reload-cache-time:s' => { name => 'reload_cache_time' }, + 'ignore-permission-errors' => { name => 'ignore_permission_errors' }, + 'use-extra-cache' => { name => 'use_extra_cache' }, + 'reload-extra-cache-time:s' => { name => 'reload_extra_cache_time' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); @@ -58,7 +60,14 @@ sub new { $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); $self->{cache_checked} = 0; - $self->{cache_uplink_loss_latency} = {}; + $self->{cache_extra_checked} = 0; + $self->{cached} = { + updated => 0, + uplink_statuses => {}, + uplinks_loss_latency => {}, + devices_statuses => {}, + devices_connection_stats => {} + }; return $self; } @@ -80,6 +89,7 @@ sub check_options { $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_token} = (defined($self->{option_results}->{api_token})) ? $self->{option_results}->{api_token} : ''; $self->{reload_cache_time} = (defined($self->{option_results}->{reload_cache_time})) ? $self->{option_results}->{reload_cache_time} : 180; + $self->{reload_cache_extra_time} = (defined($self->{option_results}->{reload_cache_extra_time})) ? $self->{option_results}->{reload_cache_extra_time} : 10; $self->{ignore_permission_errors} = (defined($self->{option_results}->{ignore_permission_errors})) ? 1 : 0; if (!defined($self->{hostname}) || $self->{hostname} eq '') { @@ -199,7 +209,7 @@ sub request_api { while (1) { my $response = $self->{http}->request( hostname => $hostname, - url_path => '/api/v0' . $options{endpoint}, + url_path => '/api/v1' . $options{endpoint}, critical_status => '', warning_status => '', unknown_status => '' @@ -364,20 +374,26 @@ sub get_organization_device_statuses { my ($self, %options) = @_; $self->cache_meraki_entities(); - my $organization_ids = $self->filter_organizations(filter_name => $options{filter_name}); - my $results = {}; - foreach my $id (@$organization_ids) { + $self->load_extra_cache(); + return $self->{cached}->{devices_statuses}->{data} if (defined($self->{cached}->{devices_statuses}->{data})); + + $self->{cached}->{updated} = 1; + $self->{cached}->{devices_statuses} = { + update_time => time(), + data => {} + }; + foreach my $id (keys %{$self->{cache_organizations}}) { my $datas = $self->request_api( - endpoint => '/organizations/' . $id . '/deviceStatuses', + endpoint => '/organizations/' . $id . '/devices/statuses', hostname => $self->get_shard_hostname(organization_id => $id) ); foreach (@$datas) { - $results->{$_->{serial}} = $_; - $results->{organizationId} = $id; + $self->{cached}->{devices_statuses}->{data}->{ $_->{serial} } = $_; + $self->{cached}->{devices_statuses}->{data}->{organizationId} = $id; } } - return $results; + return $self->{cached}->{devices_statuses}->{data}; } sub get_organization_api_requests_overview { @@ -403,24 +419,58 @@ sub get_network_device_connection_stats { my ($self, %options) = @_; $self->cache_meraki_entities(); + $self->load_extra_cache(); my $timespan = defined($options{timespan}) ? $options{timespan} : 300; $timespan = 1 if ($timespan <= 0); - return $self->request_api( - endpoint => '/networks/' . $options{network_id} . '/devices/' . $options{serial} . '/connectionStats?timespan=' . $options{timespan}, - hostname => $self->get_shard_hostname(network_id => $options{network_id}) - ); + if (!defined($self->{cached}->{devices_connection_stats}->{ $options{network_id} })) { + $self->{cached}->{updated} = 1; + $self->{cached}->{devices_connection_stats}->{ $options{network_id} } = { + update_time => time(), + data => $self->request_api( + endpoint => '/networks/' . $options{network_id} . '/wireless/devices/connectionStats?timespan=' . $options{timespan}, + hostname => $self->get_shard_hostname(network_id => $options{network_id}) + ) + }; + } + + my $result; + foreach (@{$self->{cached}->{devices_connection_stats}->{ $options{network_id} }->{data}}) { + if ($_->{serial} eq $options{serial}) { + $result = $_->{connectionStats}; + last; + } + } + + return $result; } sub get_network_device_uplink { my ($self, %options) = @_; $self->cache_meraki_entities(); + $self->load_extra_cache(); - return $self->request_api( - endpoint => '/networks/' . $options{network_id} . '/devices/' . $options{serial} . '/uplink', - hostname => $self->get_shard_hostname(network_id => $options{network_id}) - ); + if (!defined($self->{cached}->{uplink_statuses}->{ $options{organization_id} })) { + $self->{cached}->{updated} = 1; + $self->{cached}->{uplink_statuses}->{ $options{organization_id} } = { + update_time => time(), + data => $self->request_api( + endpoint => '/organizations/' . $options{organization_id} . '/uplinks/statuses', + hostname => $self->get_shard_hostname(organization_id => $options{organization_id}) + ) + }; + } + + my $result; + foreach (@{$self->{cached}->{uplink_statuses}->{ $options{organization_id} }->{data}}) { + if ($_->{serial} eq $options{serial}) { + $result = $_->{uplinks}; + last; + } + } + + return $result; } sub get_device_clients { @@ -456,7 +506,7 @@ sub get_network_device_performance { # 400 = feature not supported. 204 = no content return $self->request_api( - endpoint => '/networks/' . $options{network_id} . '/devices/' . $options{serial} . '/performance', + endpoint => '/devices/' . $options{serial} . '/appliance/performance', hostname => $self->get_shard_hostname(network_id => $options{network_id}), ignore_codes => { 400 => 1, 204 => 1 } ); @@ -466,19 +516,25 @@ sub get_organization_uplink_loss_and_latency { my ($self, %options) = @_; $self->cache_meraki_entities(); + $self->load_extra_cache(); + my $timespan = defined($options{timespan}) ? $options{timespan} : 300; $timespan = 1 if ($timespan <= 0); - if (!defined($self->{cache_uplink_loss_latency}->{ $options{organization_id} })) { - $self->{cache_uplink_loss_latency}->{ $options{organization_id} } = $self->request_api( - endpoint => '/organizations/' . $options{organization_id} . '/uplinksLossAndLatency?timespan=' . $options{timespan}, - hostname => $self->get_shard_hostname(organization_id => $options{organization_id}) - ); + if (!defined($self->{cached}->{uplinks_loss_latency}->{ $options{organization_id} })) { + $self->{cached}->{updated} = 1; + $self->{cached}->{uplinks_loss_latency}->{ $options{organization_id} } = { + update_time => time(), + data => $self->request_api( + endpoint => '/organizations/' . $options{organization_id} . '/devices/uplinksLossAndLatency?timespan=' . $options{timespan}, + hostname => $self->get_shard_hostname(organization_id => $options{organization_id}) + ) + }; } my $result = {}; - if (defined($self->{cache_uplink_loss_latency}->{ $options{organization_id} })) { - foreach (@{$self->{cache_uplink_loss_latency}->{ $options{organization_id} }}) { + if (defined($self->{cached}->{uplinks_loss_latency}->{ $options{organization_id} }->{data})) { + foreach (@{$self->{cached}->{uplinks_loss_latency}->{ $options{organization_id} }->{data}}) { if ($options{serial} eq $_->{serial}) { $result->{ $_->{uplink} } = $_; } @@ -488,6 +544,41 @@ sub get_organization_uplink_loss_and_latency { return $result; } +sub load_extra_cache { + my ($self, %options) = @_; + + return if (!defined($self->{option_results}->{use_extra_cache})); + return if ($self->{cache_extra_checked} == 1); + + $self->{cache_extra_checked} = 1; + my $has_cache_file = $self->{cache}->read(statefile => 'cache_extra_cisco_meraki_' . $self->get_token()); + my $cached = $self->{cache}->get(name => 'cached'); + $self->{cached} = $cached if (defined($cached)); + if (defined($self->{cached}->{devices_statuses}->{update_time}) && ((time() - $self->{cached}->{devices_statuses}->{update_time}) > ($self->{reload_cache_extra_time} * 60))) { + $self->{cached}->{devices_statuses} = {}; + } + + foreach my $entry (('uplink_statuses', 'uplinks_loss_latency', 'devices_connection_stats')) { + next if (!defined($self->{cached}->{$entry})); + + foreach (keys %{$self->{cached}->{$entry}}) { + if ((time() - $self->{cached}->{$entry}->{$_}->{update_time}) > ($self->{reload_cache_extra_time} * 60)) { + delete $self->{cached}->{$entry}->{$_}; + } + } + } +} + +sub close_extra_cache { + my ($self, %options) = @_; + + return if (!defined($self->{option_results}->{use_extra_cache})); + if ($self->{cached}->{updated} == 1) { + $self->{cached}->{updated} = 0; + $self->{cache}->write(data => { cached => $self->{cached} }); + } +} + 1; __END__ diff --git a/network/cisco/meraki/cloudcontroller/restapi/mode/devices.pm b/network/cisco/meraki/cloudcontroller/restapi/mode/devices.pm index 763d313f5..96e3c6798 100644 --- a/network/cisco/meraki/cloudcontroller/restapi/mode/devices.pm +++ b/network/cisco/meraki/cloudcontroller/restapi/mode/devices.pm @@ -299,7 +299,9 @@ sub new { 'filter-organization-id:s' => { name => 'filter_organization_id' }, 'filter-tags:s' => { name => 'filter_tags' }, 'add-switch-ports' => { name => 'add_switch_ports' }, - 'skip-traffic-disconnect-port' => { name => 'skip_traffic_disconnect_port' } + 'skip-traffic-disconnect-port' => { name => 'skip_traffic_disconnect_port' }, + 'skip-clients' => { name => 'skip_clients' }, + 'skip-performance' => { name => 'skip_performance' } }); return $self; @@ -350,7 +352,7 @@ sub add_uplink { my $links = $options{custom}->get_network_device_uplink( serial => $options{serial}, - network_id => $options{network_id} + organization_id => $options{organization_id} ); if (defined($links)) { @@ -479,7 +481,7 @@ sub manage_selection { next; } - $devices->{ $_->{serial} } = $_->{model}; + $devices->{ $_->{serial} } = { model => $_->{model}, organization_id => $organization->{id} }; } my $device_statuses = $options{custom}->get_organization_device_statuses(); @@ -505,7 +507,7 @@ sub manage_selection { device_ports => {} }; - if ($devices->{$serial} =~ /^(?:MG|MR)/) { + if ($devices->{$serial}->{model} =~ /^(?:MG|MR)/) { $self->add_connection_stats( custom => $options{custom}, timespan => $timespan, @@ -514,7 +516,7 @@ sub manage_selection { network_id => $cache_devices->{$serial}->{networkId} ); } - if ($devices->{$serial} =~ /^(?:MS|MG|MR|MX)/) { + if (!defined($self->{option_results}->{skip_clients}) && $devices->{$serial}->{model} =~ /^(?:MS|MG|MR|MX)/) { $self->add_clients( custom => $options{custom}, timespan => $timespan, @@ -522,12 +524,12 @@ sub manage_selection { name => $cache_devices->{$serial}->{name} ); } - if ($devices->{$serial} =~ /^(?:MV|MS|MG|MR|MX)/) { + if ($devices->{$serial}->{model} =~ /^(?:MV|MS|MG|MR|MX)/) { $self->add_uplink( custom => $options{custom}, serial => $serial, name => $cache_devices->{$serial}->{name}, - network_id => $cache_devices->{$serial}->{networkId} + organization_id => $devices->{$serial}->{organization_id} ); } if (defined($self->{option_results}->{add_switch_ports}) && $devices->{$serial} =~ /^MS/) { @@ -537,13 +539,13 @@ sub manage_selection { serial => $serial ); } - if ($devices->{$serial} =~ /^MX/) { + if ($devices->{$serial}->{model} =~ /^MX/) { $self->add_performance( custom => $options{custom}, serial => $serial, name => $cache_devices->{$serial}->{name}, network_id => $cache_devices->{$serial}->{networkId} - ); + ) if (!defined($self->{option_results}->{skip_performance})); $self->add_uplink_loss_latency( custom => $options{custom}, timespan => $timespan, @@ -557,6 +559,8 @@ sub manage_selection { if (defined($self->{global}->{ lc($device_statuses->{$serial}->{status}) })); } + $options{custom}->close_extra_cache(); + if (scalar(keys %{$self->{devices}}) <= 0) { $self->{output}->output_add(short_msg => 'no devices found'); } @@ -601,6 +605,14 @@ Filter devices by tags (Can be a regexp). Add switch port statuses and traffic. +=item B<--skip-clients> + +Don't monitor clients traffic on device. + +=item B<--skip-performance> + +Don't monitor appliance perfscore. + =item B<--skip-traffic-disconnect-port> Skip port traffic counters if port status is disconnected.