/*
 * ******************************************************
 * Copyright 2016-2020 VMware, Inc.  All Rights Reserved.
 * ******************************************************
 */

package com.vmware.vsan.samples;

import java.util.List;
import java.util.Map;

import com.vmware.common.annotations.Action;
import com.vmware.common.annotations.Option;
import com.vmware.common.annotations.Sample;
import com.vmware.connection.ConnectedVimServiceBase;
import com.vmware.vim25.AboutInfo;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.ServiceContent;
import com.vmware.vsan.connection.VsanHealthConnection;
import com.vmware.vsan.sdk.InvalidPropertyFaultMsg;
import com.vmware.vsan.sdk.NotFoundFaultMsg;
import com.vmware.vsan.sdk.NotSupportedFaultMsg;
import com.vmware.vsan.sdk.RuntimeFaultFaultMsg;
import com.vmware.vsan.sdk.VsanClusterHealthSummary;
import com.vmware.vsan.sdk.VsanFaultFaultMsg;
import com.vmware.vsan.sdk.VsanPerfNodeInformation;
import com.vmware.vsan.sdk.VsanhealthPortType;
import com.vmware.vsan.util.VsanUtil;

/**
 * <pre>
 * VsanApiSample
 *
 * This file includes sample codes for VC and ESXi sides VSAN API accessing.
 *
 * To provide an example of VC 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 example 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.
 *
 * <b>Parameters:</b>
 * url          [required] : url of the web service
 * username     [required] : username for the authentication
 * password     [required] : password for the authentication
 * clustername  [required] : VC cluster name using in cluster health query API
 *
 * <b>Command Line:</b>
 * run.bat com.vmware.vsan.samples.VsanApiSample
 * --url [webserviceurl] --username [username] --password [password] --clustername [name]
 * </pre>
 */

@Sample(name = "VsanApiSample", description = "This samples VSAN API accessing for both of VC and ESXi")
public class VsanApiSample extends ConnectedVimServiceBase {
   private String clusterName;

   @Option(
      name = "clustername",
      required = true,
      description = "The target VC cluster name"
   )
   public void setClusterName(String name) {
      this.clusterName = name;
   }

   /**
    * Get the VC cluster instance from the cluster name.
    * It will try to search the cluster under all of VC
    * data centers and return the first VC cluster matching
    * the give name
    *
    * @param serviceContent
    * @return The VC cluster instance. Return null if not found
    */
   private ManagedObjectReference getClusterFromName(
      ServiceContent serviceContent) {
      try {
         Map<String, ManagedObjectReference> clusters =
            getMOREFs.inContainerByType(serviceContent.getRootFolder(),
            "ClusterComputeResource");

         for (String cname : clusters.keySet()) {
            if (cname.equals(clusterName)) {
               return clusters.get(cname);
            }
         }
      } catch(Exception e) {
         System.err.println("Failed to get cluster name" + clusterName);
      }
      return null;
   }

   /**
    * This method demonstrates how to get vSAN cluster health status
    * by invoking the QueryClusterHealthSummary API from vSAN health
    * service against VC, how to track a task returned by vSAN API
    * and how to performance server related host information by invoking the
    * the VsanPerfQueryNodeInformation API of the Virtual performance service
    * against ESXi host
    *
    *
    * @throws RuntimeFaultFaultMsg
    * @throws InvalidPropertyFaultMsg
    * @throws NotFoundFaultMsg
    * @throws NotSupportedFaultMsg
    * @throws VsanFaultFaultMsg
    */
   @Action
   public void main()
         throws RuntimeFaultFaultMsg, InvalidPropertyFaultMsg, NotFoundFaultMsg,
         NotSupportedFaultMsg, VsanFaultFaultMsg {
      VsanHealthConnection connection = (VsanHealthConnection)super.connection;
      AboutInfo aboutInfo = serviceContent.getAbout();
      if (aboutInfo.getApiType().equals("VirtualCenter")) {
         // Here is an example of how to access VC side VSAN Health Service API.
         ManagedObjectReference cluster =
            getClusterFromName(serviceContent);
         if (cluster == null) {
            System.out.println("Cannot find VC cluster " + clusterName);
            return;
         }

         VsanhealthPortType healthPort = connection.getVsanHealthPort();
         Boolean fetchFromCache = false;
         Boolean includeObjUuid = true;
         VsanClusterHealthSummary healthSummary =
            healthPort.vsanQueryVcClusterHealthSummary(
               connection.getVsanVcHealthServiceInstanceReference(),
               VsanUtil.ConvertToHealthMoRef(cluster),
               null, null, includeObjUuid, null, fetchFromCache, null,
               null, null
            );
         System.out.println("Get vc health version " +
            healthSummary.getClusterVersions().getVcVersion());

         // Here is an example of how to track a task returned by the VSAN API.
         com.vmware.vsan.sdk.ManagedObjectReference vsanTask =
            healthPort.vsanHealthRepairClusterObjectsImmediate(
               connection.getVsanVcHealthServiceInstanceReference(),
	       VsanUtil.ConvertToHealthMoRef(cluster),
	       null
	    );

         // Need covert to vcTask to bind the MO with VC session.
         ManagedObjectReference vcTask = VsanUtil.ConvertToVcMoRef(vsanTask);

         Boolean status = VsanUtil.WaitForTasks(this.waitForValues, vcTask);
         if (status) {
            System.out.println("Repairing cluster objects task completed successfully!");
         } else {
            System.out.println("Repair cluster objects task failed!");
         }
      }

      if (aboutInfo.getApiType().equals("HostAgent")) {
         VsanhealthPortType healthPort = connection.getVsanHealthPort();

         // Here is an example of how to access ESXi side VSAN Performance
         // Service API.
         List<VsanPerfNodeInformation>  nodeInfos =
            healthPort.vsanPerfQueryNodeInformation(
               connection.getVsanPerfMgrServiceInstanceReference(), null);
         if (nodeInfos != null && nodeInfos.size() > 0) {
            VsanPerfNodeInformation nodeInfo = nodeInfos.get(0);
            System.out.println("Hostname: " + "");
            System.out.println("  version: " + nodeInfo.getVersion());
            System.out.println("  isCmmdsMaster: " + nodeInfo.isIsCmmdsMaster());
            System.out.println("  isStatsMaster: " + nodeInfo.isIsStatsMaster());
            System.out.println("  vsanMasterUuid: " + nodeInfo.getVsanMasterUuid());
            System.out.println("  vsanNodeUuid: " + nodeInfo.getVsanNodeUuid());
         }
      }
   }
}
