package centreon::esxd::common; use warnings; use strict; use Data::Dumper; use VMware::VIRuntime; use VMware::VILib; my %ERRORS = ( "OK" => 0, "WARNING" => 1, "CRITICAL" => 2, "UNKNOWN" => 3, "PENDING" => 4); my %MYERRORS = (0 => "OK", 1 => "WARNING", 3 => "CRITICAL", 7 => "UNKNOWN"); my %MYERRORS_MASK = ("CRITICAL" => 3, "WARNING" => 1, "UNKNOWN" => 7, "OK" => 0); sub errors_mask { my ($status, $state) = @_; $status |= $MYERRORS_MASK{$state}; return $status; } sub get_status { my ($state) = @_; return $ERRORS{$MYERRORS{$state}}; } sub response_client1 { my ($obj_esxd, $rh, $current_fileno, $msg) = @_; $rh->send($msg); delete $obj_esxd->{sockets}->{$current_fileno}; $obj_esxd->{read_select}->remove($rh); close $rh; } sub vmware_error { my ($obj_esxd, $lerror) = @_; $obj_esxd->{logger}->writeLogError("'" . $obj_esxd->{whoaim} . "' $lerror"); $lerror =~ s/\n/ /g; if ($lerror =~ /NoPermissionFault/i) { $obj_esxd->print_response("-2|Error: Not enough permissions\n"); } else { $obj_esxd->print_response("-1|Error: " . $lerror . "\n"); } return undef; } sub connect_vsphere { my ($logger, $whoaim, $timeout_vsphere, $session1, $service_url, $username, $password) = @_; $logger->writeLogInfo("'$whoaim' Vsphere connection in progress"); eval { $SIG{ALRM} = sub { die('TIMEOUT'); }; alarm($timeout_vsphere); $$session1 = Vim->new(service_url => $service_url); $$session1->login( user_name => $username, password => $password); alarm(0); }; if($@) { $logger->writeLogError("'$whoaim' No response from VirtualCenter server") if($@ =~ /TIMEOUT/); $logger->writeLogError("'$whoaim' You need to upgrade HTTP::Message!") if($@ =~ /HTTP::Message/); $logger->writeLogError("'$whoaim' Login to VirtualCenter server failed: $@"); return 1; } # eval { # $session_id = Vim::get_session_id(); # }; # if($@) { # writeLogFile("Can't get session_id: $@\n"); # return 1; # } return 0; } sub output_add($$$$) { my ($output_str, $output_append, $delim, $str) = (shift, shift, shift, shift); $$output_str .= $$output_append . $str; $$output_append = $delim; } sub simplify_number { my ($number, $cnt) = @_; $cnt = 2 if (!defined($cnt)); return sprintf("%.${cnt}f", "$number"); } sub convert_number { my ($number) = shift(@_); $number =~ s/\,/\./; return $number; } sub get_views { my $obj_esxd = shift; my $results; eval { $results = $obj_esxd->{session1}->get_views(mo_ref_array => $_[0], properties => $_[1]); }; if ($@) { vmware_error($obj_esxd, $@); return undef; } return $results; } sub get_view { my $obj_esxd = shift; my $results; eval { $results = $obj_esxd->{session1}->get_view(mo_ref => $_[0], properties => $_[1]); }; if ($@) { vmware_error($obj_esxd, $@); return undef; } return $results; } sub search_in_datastore { my $obj_esxd = shift; my ($ds_browse, $ds_name, $query, $return) = @_; my $result; my $files = FileQueryFlags->new(fileSize => 1, fileType => 1, modification => 1, fileOwner => 1 ); my $hostdb_search_spec = HostDatastoreBrowserSearchSpec->new(details => $files, query => $query); eval { $result = $ds_browse->SearchDatastoreSubFolders(datastorePath=> $ds_name, searchSpec=>$hostdb_search_spec); }; if ($@) { return (undef, $@) if (defined($return) && $return == 1); vmware_error($obj_esxd, $@); return undef; } return $result; } sub get_perf_metric_ids { my $obj_esxd = shift; my $perf_names = $_[0]; my $filtered_list = []; foreach (@$perf_names) { if (defined($obj_esxd->{perfcounter_cache}->{$_->{'label'}})) { foreach my $instance (@{$_->{'instances'}}) { my $metric = PerfMetricId->new(counterId => $obj_esxd->{perfcounter_cache}->{$_->{'label'}}{'key'}, instance => $instance); push @$filtered_list, $metric; } } else { $obj_esxd->{logger}->writeLogError("Metric '" . $_->{'label'} . "' unavailable."); $obj_esxd->print_response("-3|Error: Counter doesn't exist. VMware version can be too old.\n"); return undef; } } return $filtered_list; } sub generic_performance_values_historic { my ($obj_esxd, $views, $perfs, $interval, $skip_undef_counter, $multiples) = @_; my $counter = 0; my %results; eval { my $perf_metric_ids = get_perf_metric_ids($obj_esxd, $perfs); return undef if (!defined($perf_metric_ids)); my @perf_query_spec; my $tstamp = time(); my (@t) = gmtime($tstamp - $interval); my $startTime = sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", (1900+$t[5]),(1+$t[4]),$t[3],$t[2],$t[1],$t[0]); (@t) = gmtime($tstamp); my $endTime = sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", (1900+$t[5]),(1+$t[4]),$t[3],$t[2],$t[1],$t[0]); foreach (@$views) { if ($interval == 20) { push @perf_query_spec, PerfQuerySpec->new(entity => $_, metricId => $perf_metric_ids, format => 'normal', intervalId => 20, startTime => $startTime, endTime => $endTime, maxSample => 1); } else { push @perf_query_spec, PerfQuerySpec->new(entity => $_, metricId => $perf_metric_ids, format => 'normal', intervalId => $interval, startTime => $startTime, endTime => $endTime ); #maxSample => 1); } } my $perfdata = $obj_esxd->{perfmanager_view}->QueryPerf(querySpec => \@perf_query_spec); if (!$$perfdata[0] || !defined($$perfdata[0]->value)) { $obj_esxd->print_response("-3|Error: Cannot get value for counters. Maybe you have call a wrong instance.\n"); return undef; } foreach my $val (@$perfdata) { foreach (@{$val->{value}}) { if (defined($skip_undef_counter) && $skip_undef_counter == 1 && !defined($_->value)) { $results{$_->id->counterId . ":" . (defined($_->id->instance) ? $_->id->instance : "")} = undef; next; } elsif (!defined($_->value)) { $obj_esxd->print_response("-3|Error: Cannot get value for counters. Maybe there is time sync problem (check the esxd server and the target also).\n"); return undef; } if (defined($multiples) && $multiples == 1) { $results{$val->{entity}->{value} . ":" . $_->id->counterId . ":" . (defined($_->id->instance) ? $_->id->instance : "")} = $_->value; } else { $results{$_->id->counterId . ":" . (defined($_->id->instance) ? $_->id->instance : "")} = $_->value; } } } }; if ($@) { $obj_esxd->{logger}->writeLogError("'" . $obj_esxd->{whoaim} . "' $@"); return undef; } return \%results; } sub cache_perf_counters { my $obj_esxd = shift; eval { $obj_esxd->{perfmanager_view} = $obj_esxd->{session1}->get_view(mo_ref => $obj_esxd->{session1}->get_service_content()->perfManager, properties => ['perfCounter', 'historicalInterval']); foreach (@{$obj_esxd->{perfmanager_view}->perfCounter}) { my $label = $_->groupInfo->key . "." . $_->nameInfo->key . "." . $_->rollupType->val; $obj_esxd->{perfcounter_cache}->{$label} = {'key' => $_->key, 'unitkey' => $_->unitInfo->key}; $obj_esxd->{perfcounter_cache_reverse}->{$_->key} = $label; } my $historical_intervals = $obj_esxd->{perfmanager_view}->historicalInterval; foreach (@$historical_intervals) { if ($obj_esxd->{perfcounter_speriod} == -1 || $obj_esxd->{perfcounter_speriod} > $_->samplingPeriod) { $obj_esxd->{perfcounter_speriod} = $_->samplingPeriod; } } # Put refresh = 20 (for ESX check) if ($obj_esxd->{perfcounter_speriod} == -1) { $obj_esxd->{perfcounter_speriod} = 20; } }; if ($@) { $obj_esxd->{logger}->writeLogError("'" . $obj_esxd->{whoaim} . "' $@"); return 1; } return 0; } sub get_entities_host { my ($obj_esxd, $view_type, $filters, $properties) = @_; my $entity_views; eval { $entity_views = $obj_esxd->{session1}->find_entity_views(view_type => $view_type, properties => $properties, filter => $filters); }; if ($@) { $obj_esxd->{logger}->writeLogError("'" . $obj_esxd->{whoaim} . "' $@"); eval { $entity_views = $obj_esxd->{session1}->find_entity_views(view_type => $view_type, properties => $properties, filter => $filters); }; if ($@) { vmware_error($obj_esxd, $@); return undef; } } if (!@$entity_views) { my $status = 0; $status = errors_mask($status, 'UNKNOWN'); $obj_esxd->print_response(get_status($status) . "|Object $view_type does not exist.\n"); return undef; } #eval { # $$entity_views[0]->update_view_data(properties => $properties); #}; #if ($@) { # writeLogFile("$@"); # my $lerror = $@; # $lerror =~ s/\n/ /g; # print "-1|Error: " . $lerror . "\n"; # return undef; #} return $entity_views; } sub performance_errors { my ($obj_esxd, $values) = @_; # Error counter not available or other from function return 1 if (!defined($values) || scalar(keys(%$values)) <= 0); return 0; } sub is_accessible { my ($accessible) = @_; if ($accessible !~ /^true|1$/) { return 0; } return 1; } sub is_connected { my ($connection_state) = @_; if ($connection_state !~ /^connected$/i) { return 0; } return 1; } sub is_running { my ($power_state) = @_; if ($power_state !~ /^poweredOn$/i) { return 0; } return 1; } sub datastore_state { my ($obj_esxd, $ds, $accessible) = @_; if ($accessible !~ /^true|1$/) { my $output = "Datastore '" . $ds . "' not accessible. Can be disconnected."; my $status = errors_mask(0, $obj_esxd->{centreonesxd_config}->{datastore_state_error}); $obj_esxd->print_response(get_status($status) . "|$output\n"); return 0; } return 1; } sub vm_state { my ($obj_esxd, $vm, $connection_state, $power_state, $nocheck_ps) = @_; if ($connection_state !~ /^connected$/i) { my $output = "VM '" . $vm . "' not connected. Current Connection State: '$connection_state'."; my $status = errors_mask(0, $obj_esxd->{centreonesxd_config}->{vm_state_error}); $obj_esxd->print_response(get_status($status) . "|$output\n"); return 0; } if (!defined($nocheck_ps) && $power_state !~ /^poweredOn$/i) { my $output = "VM '" . $vm . "' not running. Current Power State: '$power_state'."; my $status = errors_mask(0, $obj_esxd->{centreonesxd_config}->{vm_state_error}); $obj_esxd->print_response(get_status($status) . "|$output\n"); return 0; } return 1; } sub host_state { my ($obj_esxd, $host, $connection_state) = @_; if ($connection_state !~ /^connected$/i) { my $output = "Host '" . $host . "' not connected. Current Connection State: '$connection_state'."; my $status = errors_mask(0, $obj_esxd->{centreonesxd_config}->{host_state_error}); $obj_esxd->print_response(get_status($status) . "|$output\n"); return 0; } return 1; } sub stats_info { my ($obj_esxd, $rh, $current_fileno, $args) = @_; my $output; my $status = 0; $$args[0] ='' if (!defined($$args[0])); $$args[1] = '' if (!defined($$args[1])); my $num_connection = scalar(keys(%{$obj_esxd->{sockets}})); $output = "'$num_connection' total client connections | connection=$num_connection;$$args[0];$$args[1];0; requests=" . $obj_esxd->{counter}; if ($$args[1] ne '' and $num_connection >= $$args[1]) { $status = errors_mask($status, 'CRITICAL'); } elsif ($$args[0] ne '' and $num_connection >= $$args[0]) { $status = errors_mask($status, 'WARNING'); } response_client1($obj_esxd, $rh, $current_fileno, get_status($status) . "|$output\n"); } 1;