#!/usr/bin/env ruby
"""
Copyright 2016-2017 VMware, Inc.  All rights reserved.

Require a minimum Ruby version of 1.8.7.

This file includes sample codes for vCenter and ESXi sides vSAN API accessing.

To provide an example of vCenter side vSAN API access, it shows how to get vSAN
cluster health status by invoking the QueryClusterHealthSummary() API of the
VsanVcClusterHealthSystem MO.

To provide an exmple of ESXi side vSAN API access, it shows how to get
performance server related host information by invoking the
VsanPerfQueryNodeInformation() API of the VsanPerformanceManager MO.

"""

require 'rbvmomi'
require 'rbvmomi/trollop'
# Use require_relative if vsanmgmt.api.rb file is copied to current work
# directory, otherwise, use 'require' if the file is in ruby path.
require_relative 'vsanmgmt.api'
#require 'vsanmgmt.api'
require_relative 'vsanapiutils'

opts = Trollop.options do
  banner <<-EOS
Check health summary and print cluster status.

Usage:
    vsanapisamples.rb [options] CLUSTER

VIM connection options:
    EOS

    rbvmomi_connection_opts

    text <<-EOS

Other options:
  EOS
end

Trollop.die("must specify host") unless opts[:host]

def getClusterInstance(clusterName, serviceInstance)
  cluster = nil
  datacenters = serviceInstance.content.rootFolder.childEntity
  datacenters.each do |datacenter|
    cluster = datacenter.hostFolder.childEntity.find { |x| x.name == clusterName }
    if cluster != nil
      break
    end
  end
  return cluster
end

opts[:ssl] = true
opts[:insecure] = true
conn = RbVmomi::VIM.connect opts

# For detecting whether the host is vCenter or ESXi.
aboutInfo = conn.serviceContent.about

if aboutInfo.apiType == 'VirtualCenter'
  majorApiVersion = aboutInfo.apiVersion.split('.')[0]
  abort "The Virtual Center with version #{aboutInfo.apiVersion} \
    (lower than 6.0) is not supported." if (majorApiVersion.to_i < 6)

  cluster_name = ARGV[0] or Trollop.die("no cluster name given")

  cluster = getClusterInstance(cluster_name, conn.serviceInstance)
  abort "Cluster #{cluster_name} is not found for #{opts[:host]}" unless cluster

  # Get vSAN health system from the vCenter Managed Object references.
  vhs = conn.vsan.vsanClusterHealthSystem

  # vSAN cluster health summary can be cached at vCenter.
  fetchFromCache = true
  print "Do you want to fetch the cluster health from cache if exists?(y/n):"
  fetchFromCacheAnswer = STDIN.gets.chomp
  fetchFromCache = false if fetchFromCacheAnswer.downcase == 'n'
  puts "Fetching cluster health from cached state: #{fetchFromCache ? 'Yes' : 'No'}"

  healthSummary = vhs.VsanQueryVcClusterHealthSummary(
    :cluster => cluster,
    :includeObjUuids => true,
    :fetchFromCache => fetchFromCache
  )
  clusterStatus = healthSummary.clusterStatus

  puts "Cluster #{cluster_name} Status: #{clusterStatus.status}"
  clusterStatus.trackedHostsStatus.each do |result|
    puts "Host #{result.hostname} status: #{result.status}"
    result.issues.each do |issue|
      puts "Issue: #{issue}"
    end
  end

  # Here is an example of how to track a task returned by the VSAN API
  vsanTask = vhs.VsanHealthRepairClusterObjectsImmediate(:cluster => cluster)
  vcTask = vsanTask.onConnection conn
  begin
    vcTask.wait_for_completion
    puts "Repairing cluster objects task completed with state: #{vcTask.info.state}"
  rescue Exception => ex
    pp ex
    raise
  end
end

if aboutInfo.apiType == 'HostAgent'
  majorApiVersion = aboutInfo.apiVersion.split('.')[0]
  abort "The ESXi with version #{aboutInfo.apiVersion} (lower than 6.0) is not \
    supported." if (majorApiVersion.to_i < 6)

  # Get vSAN performance manager from the ESXi Managed Object references.
  vpm = conn.vsan.vsanPerformanceManager

  nodeInfo = vpm.VsanPerfQueryNodeInformation().first

  puts "Hostname: #{opts[:host]}"
  puts "  version: #{nodeInfo.version}"
  puts "  isCmmdsMaster: #{nodeInfo.isCmmdsMaster}"
  puts "  isStatsMaster: #{nodeInfo.isStatsMaster}"
  puts "  vsanMasterUuid: #{nodeInfo.vsanMasterUuid}"
  puts "  vsanNodeUuid: #{nodeInfo.vsanNodeUuid}"

end
