#!/usr/bin/perl -w
#
# Copyright (c) 2016-2019 VMware, Inc.  All rights reserved.

use strict;
use warnings;

use FindBin;
use lib "$FindBin::Bin/../";

use VMware::VIRuntime;
use VMware::VIMRuntime;

use VsanapiUtils;

$SIG{__DIE__} = sub{Util::disconnect()};
$SIG{INT} = sub{on_interrupt();};

$Util::script_version = "1.0";

my %opts = (
   cluster_name => {
      type => "=s",
      help => "Cluster name",
      required => 0,
   },
);

#Assuming the binding files are in the same directory
#of this script.
load_vsanmgmt_binding_files("./VIM25VsanmgmtStub.pm",
                            "./VIM25VsanmgmtRuntime.pm");
Opts::add_options(%opts);
Opts::parse();
Opts::validate();
Util::connect();
main();
Util::disconnect();

sub on_interrupt {
   Util::disconnect();
   exit;
}
sub trim($)
{
   my $string = shift;
   $string =~ s/^\s+//;
   $string =~ s/\s+$//;
   return $string;
}

sub onTaskUpdated {
   my $progress = shift @_;
   Util::trace(0, "Task updated with progress($progress%)\n");
}

sub main {
   Util::trace(0, "\nConnection Successful\n");
   my $service_content = Vim::get_service_content();
   my $apiType = $service_content->about->apiType;

   if($apiType eq "VirtualCenter") {
      my $cluster_name = Opts::get_option("cluster_name");
      my $cluster_view = undef;
      if (not defined($cluster_name)) {
         croak "Please provide the cluster name for \
VC connection(option --cluster_name).";
      }
      $cluster_view = Vim::find_entity_view(
                            view_type => 'ClusterComputeResource',
                            filter => { 'name' => $cluster_name },
                            properties => ['name']);
      if ($cluster_view) {
         Util::trace(0, "cluster name: ".$cluster_view->name."\n");
      }
      if (not $cluster_view) {
         croak "We can not get the cluster. \
Please check if the cluster name or id is correct.";
      }

      my %vc_mos = get_vsan_vc_mos();

      my $health_system_view = $vc_mos{"vsan-cluster-health-system"};

      if ($health_system_view) {
         #VSAN cluster health summary can be cached at VC.
         my $fetchFromCache = "true";
         my $fetchPrompt =
<<"END_MESSAGE";
Do you want to fetch the cluster health from cache if exists?(y/n):\n
END_MESSAGE
         Util::trace(0, $fetchPrompt);
         my $fetchFromCacheAnswer = trim <STDIN>;

         if (lc $fetchFromCacheAnswer eq 'n') {
            $fetchFromCache = "false";
         }
         Util::trace(0, "Fetching cluster health from cached state: "
                        .$fetchFromCache."\n");

         my $summary = $health_system_view->VsanQueryVcClusterHealthSummary(
                                           cluster => $cluster_view,
                                           includeObjUuids => "true",
                                           fetchFromCache =>  $fetchFromCache);
         my $clusterStatus = $summary->clusterStatus;
         Util::trace(0,
            "cluster $cluster_name status: $clusterStatus->{'status'}\n");

         #Here is an example of how to track a task returned by the VSAN API
         my $vsan_task =
            $health_system_view->VsanHealthRepairClusterObjectsImmediate(
                                                   cluster => $cluster_view);
         #Use a parent mo view as to wait for the task.
         $cluster_view->waitForTask($vsan_task, \&onTaskUpdated);
         Util::trace(0, "Repairing task completed.\n");

      } else {
         croak "We can not get vsan cluster health system managed object. \
Check your connection and make sure health is enabled";
      }

   } elsif($apiType eq "HostAgent") {
      my %esx_mos = get_vsan_esx_mos();
      my $perf_view = $esx_mos{"vsan-performance-manager"};
      my $nodeInfo = $perf_view->VsanPerfQueryNodeInformation();

      my $url = new URI::URL Vim::get_service_url();
      Util::trace(0, "Host: ".$url->host."\n");
      Util::trace(0, "  version: $nodeInfo->{'version'}\n");
      Util::trace(0, "  isCmmdsMaster: $nodeInfo->{'isCmmdsMaster'}\n");
      Util::trace(0, "  isStatsMaster: $nodeInfo->{'isStatsMaster'}\n");
      Util::trace(0, "  vsanMasterUuid: $nodeInfo->{'vsanMasterUuid'}\n");
      Util::trace(0, "  vsanNodeUuid: $nodeInfo->{'vsanNodeUuid'}\n");
   }
}
__END__

=head1 NAME

vsanapisample.pl - Connects to and disconnects from either an ESX host or
                   a VirtualCenter server, and demostrate vsanapi on both
                   ESX host and VC server.

=head1 SYNOPSIS

 vsanapisample.pl [options]

=head1 DESCRIPTION

This VI Perl command-line utility connects to an ESX host or a VirtualCenter
server,
- Demostrate sample code for how to get VSAN cluster health
  status by invoking the QueryClusterHealthSummary API of the
  VsanVcClusterHealthSystem MO on VC side.
- Demostrate sample code for how to get performance server
  related host information by invoking the
  VsanPerfQueryNodeInformation API of the VsanPerformanceManager MO
  on Exsi server side.

=head1 EXAMPLES

VC:
 vsanapisample.pl --url https://<host>:<port>/sdk/vimService
            --username myuser --password mypassword --cluster_name mycluster
 vsanapisample.pl --url https://<host>:<port>/sdk/vimService
            --username myuser --password mypassword --cluster_moid cluster_id
ESX:
 vsanapisample.pl --url https://<host>:<port>/sdk
            --username myuser --password mypassword

=head1 SUPPORTED PLATFORMS

All operations work with VMware VirtualCenter 6.0 or later.

All operations work with VMware ESX 6.0 or later.


