/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package com.emc.storageos.vcentercontroller; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.model.property.PropertyInfo; import com.emc.storageos.vcentercontroller.exceptions.VcenterObjectConnectionException; import com.emc.storageos.vcentercontroller.exceptions.VcenterObjectNotFoundException; import com.emc.storageos.vcentercontroller.exceptions.VcenterServerConnectionException; import com.emc.storageos.vcentercontroller.exceptions.VcenterSystemException; import com.vmware.vim25.ClusterConfigSpecEx; import com.vmware.vim25.HostConfigFault; import com.vmware.vim25.HostConnectSpec; import com.vmware.vim25.HostScsiDisk; import com.vmware.vim25.HostStorageDeviceInfo; import com.vmware.vim25.HostSystemConnectionState; import com.vmware.vim25.HostSystemPowerState; import com.vmware.vim25.InvalidLogin; import com.vmware.vim25.ScsiLun; import com.vmware.vim25.TaskInfo; import com.vmware.vim25.VirtualMachinePowerState; import com.vmware.vim25.VmfsDatastoreCreateSpec; import com.vmware.vim25.VmfsDatastoreInfo; import com.vmware.vim25.VmfsDatastoreOption; import com.vmware.vim25.mo.ClusterComputeResource; import com.vmware.vim25.mo.Datacenter; import com.vmware.vim25.mo.Datastore; import com.vmware.vim25.mo.HostDatastoreSystem; import com.vmware.vim25.mo.HostStorageSystem; import com.vmware.vim25.mo.HostSystem; import com.vmware.vim25.mo.InventoryNavigator; import com.vmware.vim25.mo.ManagedEntity; import com.vmware.vim25.mo.ResourcePool; import com.vmware.vim25.mo.ServiceInstance; import com.vmware.vim25.mo.Task; import com.vmware.vim25.mo.VirtualMachine; /** * Created with IntelliJ IDEA. * User: alaplante * Date: 9/16/14 * Time: 11:11 AM * To change this template use File | Settings | File Templates. */ public class VcenterApiClient { private final static Logger _log = LoggerFactory.getLogger(VcenterApiClient.class); private static int DEFAULT_PORT = 443; private ServiceInstance serviceInstance; private VcenterClusterConfigurer clusterConfigurer = new VcenterClusterConfigurerPropertyInfoImpl(); private PropertyInfo propertyInfo; private ServiceInstance createServiceInstance(String vcenterUrl, String vcenterUsername, String vcenterPassword) throws VcenterServerConnectionException { return connect(vcenterUrl, vcenterUsername, vcenterPassword); } public VcenterApiClient(PropertyInfo propertyInfo) { this.propertyInfo = propertyInfo; } private ServiceInstance connect(String url, String user, String password) throws VcenterServerConnectionException { try { return new ServiceInstance(new URL(url), user, password, true); } catch (InvalidLogin il) { _log.error("Invalid vCenter server credentials"); throw new VcenterServerConnectionException("Invalid vCenter server credentials"); } catch (Exception e) { _log.error("Error connecting to vCenter server"); throw new VcenterServerConnectionException("Error connecting to vCenter server"); } } public void setup(String vcenterIp, String vcenterUsername, String vcenterPassword, Integer portNumber) throws VcenterServerConnectionException { int port = (portNumber == null) ? DEFAULT_PORT : portNumber; String vcenterUrl = "https://" + vcenterIp + ":" + port + "/sdk"; serviceInstance = createServiceInstance(vcenterUrl, vcenterUsername, vcenterPassword); _log.info("Connected to vcenter " + vcenterIp + " API version " + serviceInstance.getAboutInfo().getApiVersion()); } public void destroy() { if (serviceInstance != null) { serviceInstance.getServerConnection().logout(); _log.info("Log out successful"); } } private ClusterComputeResource searchClusterComputeResource(String datacenterName, String clusterNameOrMoRef) throws VcenterSystemException, VcenterObjectNotFoundException { if (serviceInstance == null) { _log.error("Invoke setup to open connection before using client"); throw new VcenterSystemException("Invoke setup to open connection before using client"); } try { // MoRef search first _log.info("Search cluster by MoRef " + clusterNameOrMoRef); ManagedEntity[] clusterComputeResources = new InventoryNavigator(serviceInstance.getRootFolder()) .searchManagedEntities("ClusterComputeResource"); for (ManagedEntity managedEntity : clusterComputeResources) { if (managedEntity.getMOR().getVal().equals(clusterNameOrMoRef)) { _log.info("Found cluster " + managedEntity.getName() + " by MoRef " + clusterNameOrMoRef); return (ClusterComputeResource) managedEntity; } } // Then name _log.info("Search cluster by name " + clusterNameOrMoRef + " in datacenter " + datacenterName); Datacenter datacenter = (Datacenter) new InventoryNavigator(serviceInstance.getRootFolder()).searchManagedEntity("Datacenter", datacenterName); if (datacenter == null) { _log.error("Datacenter " + datacenterName + " does not exist"); throw new VcenterObjectNotFoundException("Datacenter " + datacenterName + " does not exist"); } ClusterComputeResource clusterComputeResource = (ClusterComputeResource) new InventoryNavigator(datacenter) .searchManagedEntity("ClusterComputeResource", clusterNameOrMoRef); if (clusterComputeResource == null) { _log.error("Cluster " + clusterNameOrMoRef + " does not exist"); throw new VcenterObjectNotFoundException("Cluster " + clusterNameOrMoRef + " does not exist"); } return clusterComputeResource; } catch (VcenterObjectNotFoundException e) { throw e; } catch (Exception e) { _log.error("searchClusterComputeResources exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } /* * Provide names of the vCenter elements and method will locate the MangedEntity representation * Each search is done within context of previous entity thus there is a dependency * Cluster * Datacenter * Host * Parameters are optional (ie, leave host null to only search datacenter and cluster) * Must provide parent element name or child will not be searched * hostConnectedPoweredOn ensures host is operational and ready for calls */ private Map<String, ManagedEntity> createManagedEntityMap(String datacenterName, String clusterNameOrMoRef, String hostname, boolean hostConnectedPoweredOn) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { if (serviceInstance == null) { _log.error("Invoke setup to open connection before using client"); throw new VcenterSystemException("Invoke setup to open connection before using client"); } try { Map<String, ManagedEntity> vcenterManagedEntityMap = new HashMap<String, ManagedEntity>(); if (datacenterName != null && !datacenterName.trim().equals("")) { Datacenter datacenter = (Datacenter) new InventoryNavigator(serviceInstance.getRootFolder()).searchManagedEntity( "Datacenter", datacenterName); if (datacenter == null) { _log.error("Datacenter " + datacenterName + " does not exist"); throw new VcenterObjectNotFoundException("Datacenter " + datacenterName + " does not exist"); } vcenterManagedEntityMap.put("Datacenter", datacenter); if (clusterNameOrMoRef != null && !clusterNameOrMoRef.trim().equals("")) { ClusterComputeResource clusterComputeResource = searchClusterComputeResource(datacenterName, clusterNameOrMoRef); vcenterManagedEntityMap.put("ClusterComputeResource", clusterComputeResource); if (hostname != null && !hostname.trim().equals("")) { HostSystem hostSystem = findByHostname(clusterComputeResource, hostname); if (hostSystem == null) { _log.error("Host " + hostname + " does not exist"); throw new VcenterObjectNotFoundException("Host " + hostname + " does not exist"); } if (hostConnectedPoweredOn) { checkHostConnectedPoweredOn(hostSystem); } vcenterManagedEntityMap.put("HostSystem", hostSystem); } } } return vcenterManagedEntityMap; } catch (VcenterSystemException | VcenterObjectNotFoundException | VcenterObjectConnectionException e) { throw e; } catch (Exception e) { _log.error("getVcenterObjects exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } public String createCluster(String datacenterName, String clusterNameOrMoRef) throws VcenterSystemException, VcenterObjectNotFoundException { try { createManagedEntityMap(datacenterName, null, null, false).get("Datacenter"); // Ensures datacenter exists ClusterComputeResource clusterComputeResource = null; try { clusterComputeResource = searchClusterComputeResource(datacenterName, clusterNameOrMoRef); } catch (VcenterObjectNotFoundException e) { _log.info("Ignore VcenterObjectNotFoundException on cluster search since we are creating new cluster"); } if (clusterComputeResource != null) { _log.error("Cluster " + clusterNameOrMoRef + " already exists"); throw new VcenterSystemException("Cluster " + clusterNameOrMoRef + " already exists"); } return createOrUpdateCluster(datacenterName, clusterNameOrMoRef); } catch (VcenterSystemException | VcenterObjectNotFoundException e) { throw e; } catch (Exception e) { _log.error("createCluster exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } public String updateCluster(String datacenterName, String clusterNameOrMoRef) throws VcenterSystemException, VcenterObjectNotFoundException { try { createManagedEntityMap(datacenterName, clusterNameOrMoRef, null, false); // Make call to check that cluster exists return createOrUpdateCluster(datacenterName, clusterNameOrMoRef); } catch (VcenterSystemException | VcenterObjectNotFoundException e) { throw e; } catch (Exception e) { _log.error("updateCluster exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } private String createOrUpdateCluster(String datacenterName, String clusterNameOrMoRef) throws VcenterSystemException, VcenterObjectNotFoundException { try { _log.info("Request to create or update cluster " + clusterNameOrMoRef + " in datacenter " + datacenterName); Map<String, ManagedEntity> managedEntityMap = createManagedEntityMap(datacenterName, null, null, false); Datacenter datacenter = (Datacenter) managedEntityMap.get("Datacenter"); // Ensure datacenter exists ClusterComputeResource clusterComputeResource = null; try { clusterComputeResource = searchClusterComputeResource(datacenterName, clusterNameOrMoRef); _log.info("Cluster " + clusterNameOrMoRef + " already exists so no work to do"); } catch (VcenterObjectNotFoundException e) { _log.info("Cluster " + clusterNameOrMoRef + " does not exist and will be created"); ClusterConfigSpecEx clusterConfigSpecEx = clusterConfigurer.configure(propertyInfo); clusterComputeResource = datacenter.getHostFolder().createClusterEx(clusterNameOrMoRef, clusterConfigSpecEx); _log.info("Cluster " + clusterNameOrMoRef + " created with key " + clusterComputeResource.getMOR().getVal()); } return clusterComputeResource.getMOR().getVal(); } catch (VcenterSystemException | VcenterObjectNotFoundException e) { throw e; } catch (Exception e) { _log.error("Exception creating cluster: " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } private HostSystem findByHostname(ClusterComputeResource clusterComputeResource, String hostname) throws VcenterSystemException { try { ManagedEntity[] hostSystems = new InventoryNavigator(clusterComputeResource).searchManagedEntities("HostSystem"); _log.info("Search for host " + hostname + " by exact match"); for (ManagedEntity hostManagedEntity : hostSystems) { HostSystem hostSystem = (HostSystem) hostManagedEntity; if (hostSystem.getName().equalsIgnoreCase(hostname)) { _log.info("Found host by exact match based search " + hostSystem.getName()); return hostSystem; } } // Exact match failed so its qualified in one system but not in the other _log.info("Search for host " + hostname + " by FQDN and unqualified searches"); Collection<HostSystem> hosts = new ArrayList<HostSystem>(); if (hostname.contains(".")) { // FQDN for (ManagedEntity hostManagedEntity : hostSystems) { HostSystem hostSystem = (HostSystem) hostManagedEntity; if (hostSystem.getName().toLowerCase().equalsIgnoreCase(hostname.split("\\.")[0])) { _log.info("Found host by FQDN based search " + hostSystem.getName()); hosts.add(hostSystem); } } } else { // unqualified for (ManagedEntity hostManagedEntity : hostSystems) { HostSystem hostSystem = (HostSystem) hostManagedEntity; if (hostSystem.getName().toLowerCase().startsWith(hostname.toLowerCase())) { _log.info("Found host by unqualified based search " + hostSystem.getName()); hosts.add(hostSystem); } } } if (hosts.isEmpty()) { _log.info("Host " + hostname + " not found"); } else if (hosts.size() > 1) { _log.info("Host " + hostname + " search returned ambiguous result set of many hosts"); } else { return hosts.iterator().next(); } return null; } catch (Exception e) { _log.error("findByHostname exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } private String getHostCertificate(String hostname, String username, String password) throws VcenterSystemException, VcenterObjectConnectionException { try { Integer hostOperationTimeout = Integer.parseInt(propertyInfo.getProperty("vcenter_host_operation_timeout")); Integer sslTimeout = hostOperationTimeout * 1000; Integer retryCount = 1; Long startTimeMillis = System.currentTimeMillis(); Long cutoffTimeMillis = startTimeMillis + sslTimeout; VcenterHostCertificateGetter.HostConnectionStatus status = VcenterHostCertificateGetter.getInstance().getConnectionStatus( hostname, 443, "/host/ssl_cert", username, password, 300); while ((System.currentTimeMillis() < cutoffTimeMillis) && status == VcenterHostCertificateGetter.HostConnectionStatus.UNREACHABLE) { _log.info("Host " + hostname + " is unreachable after attempt " + retryCount + " - Retry SSL cert request"); Thread.sleep(10000); // Retry is time based and if each retry executes very quickly (ie milliseconds) then we should // throttle and only retry every 10 seconds status = VcenterHostCertificateGetter.getInstance().getConnectionStatus(hostname, 443, "/host/ssl_cert", username, password, 300); retryCount++; } String errorSuggestion = null; if (status == VcenterHostCertificateGetter.HostConnectionStatus.UNREACHABLE) { errorSuggestion = "Ensure host is powered on and responsive. Can be caused by intermittent or temporary connectivity issue thus retry recommended"; } else if (status == VcenterHostCertificateGetter.HostConnectionStatus.UNKNOWN) { errorSuggestion = "Ensure hostname is correct and DNS resolvable"; } else if (status == VcenterHostCertificateGetter.HostConnectionStatus.UNAUTHORIZED) { errorSuggestion = "Ensure host credentials are correct"; } if (errorSuggestion != null) { _log.error("Host " + hostname + " not reachable in state " + status + " - " + errorSuggestion); throw new VcenterObjectConnectionException("Host " + hostname + " not reachable in state " + status + " - " + errorSuggestion); } String thumbprint = null; try { thumbprint = VcenterHostCertificateGetter.getInstance().getSSLThumbprint(hostname, 443, "/host/ssl_cert", username, password, sslTimeout); } catch (Exception e) { _log.info("Error getting host " + hostname + " SSL certificate " + e); thumbprint = VcenterHostCertificateGetter.getInstance().getSSLThumbprint(hostname, 443, "/host/ssl_cert", username, password, sslTimeout); } if (thumbprint == null || thumbprint.equals("")) { _log.error("Could not retrieve host " + hostname + " SSL certificate"); throw new VcenterSystemException("Could not retrieve host " + hostname + " SSL certificate"); } return thumbprint; } catch (VcenterSystemException | VcenterObjectConnectionException e) { throw e; } catch (Exception e) { _log.error("getHostCertificate exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } private void trackHostTasks(HostSystem hostSystem, Integer timeout) throws VcenterSystemException { try { // Track and wait for other tasks, ie HA, initiated by the add before progressing String hostname = hostSystem.getName(); int taskStartupWait = 5 * 1000; _log.info("Wait " + taskStartupWait + " seconds for any tasks to run against host before monitoring"); Thread.sleep(taskStartupWait); // wait for post register tasks to begin Task[] tasks = hostSystem.getRecentTasks() == null ? new Task[0] : hostSystem.getRecentTasks(); _log.info("Host " + hostname + " has " + tasks.length + " tasks currently running or queued to run"); if (tasks.length > 0) { VcenterTaskMonitor taskMonitor = new VcenterTaskMonitor(timeout); // stateful since this instance used for ALL tasks - // timeout is basically for ALL tasks to finish in for (Task task : tasks) { TaskInfo taskInfo = task.getTaskInfo(); _log.info("Begin waiting on task " + taskInfo.getName() + " " + taskInfo.getDescriptionId()); taskMonitor.waitForTask(task); // call blocks until task reaches terminal state or timeout is met _log.info("Quit waiting for task " + taskInfo.getName() + " " + taskInfo.getDescriptionId() + " in state " + taskInfo.getState()); } _log.info("Done waiting for tasks for host " + hostname); for (Task task : tasks) { TaskInfo taskInfo = task.getTaskInfo(); _log.info("Host " + hostname + " task " + taskInfo.getName() + " " + taskInfo.getDescriptionId() + " in state " + taskInfo.getState()); } } } catch (Exception e) { _log.error("trackHostTasks exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } private void reconnectHost(HostSystem hostSystem) throws VcenterSystemException { try { String hostname = hostSystem.getName(); HostSystemConnectionState hostSystemConnectionState = hostSystem.getRuntime().getConnectionState(); if (hostSystemConnectionState == HostSystemConnectionState.disconnected || hostSystemConnectionState == HostSystemConnectionState.notResponding) { Integer operationTimeout = Integer.parseInt(propertyInfo.getProperty("vcenter_operation_timeout")); _log.info("Host " + hostname + " is in a " + hostSystemConnectionState + "state - Attempt to reconnect"); Task reconnectHostTask = hostSystem.reconnectHost_Task(null); // might need to provide conn info, no arg should use // 'defaults' guessing means what it was registered originally // with VcenterTaskMonitor.TaskStatus taskStatus = (new VcenterTaskMonitor(operationTimeout)).monitor(reconnectHostTask); // wait // configured // timeout _log.info("After running reconnect task for host " + hostname + " the task result is " + taskStatus + " and host is in connection state " + hostSystem.getRuntime().getConnectionState()); } } catch (Exception e) { _log.error("reconnectHost exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } public void enterMaintenanceMode(String datacenterName, String clusterNameOrMoRef, String hostname) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { try { _log.info("Request to enter maintenance mode for host " + hostname + " in datacenter " + datacenterName + " cluster " + clusterNameOrMoRef); enterMaintenanceModeHost((HostSystem) createManagedEntityMap(datacenterName, clusterNameOrMoRef, hostname, true).get( "HostSystem")); } catch (VcenterSystemException | VcenterObjectNotFoundException | VcenterObjectConnectionException e) { throw e; } catch (Exception e) { _log.error("enterMaintenanceMode exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } private void enterMaintenanceModeHost(HostSystem hostSystem) throws VcenterSystemException { try { String hostname = hostSystem.getName(); if (!hostSystem.getRuntime().isInMaintenanceMode()) { Integer operationTimeout = Integer.parseInt(propertyInfo.getProperty("vcenter_operation_timeout")); _log.info("Host " + hostname + " is not in maintenance mode - Attempt to enter"); Task enterMaintenanceModeTask = hostSystem.enterMaintenanceMode(operationTimeout, true); VcenterTaskMonitor taskMonitor = new VcenterTaskMonitor(operationTimeout); VcenterTaskMonitor.TaskStatus taskStatus = taskMonitor.monitor(enterMaintenanceModeTask); _log.info("After running enter maintenance mode task for host " + hostname + " the task result is " + taskStatus + " and host is in maintenance mode " + hostSystem.getRuntime().isInMaintenanceMode()); if (!hostSystem.getRuntime().isInMaintenanceMode()) { _log.error("Host " + hostname + " failed to enter maintenance mode"); String message = "Host " + hostname + " failed to enter maintenance mode. " + "Safety check for running virtual machines failed. " + "Vcenter was either unable to migrate them or ViPR could not verify VMs are not running."; if (taskStatus == VcenterTaskMonitor.TaskStatus.ERROR) { throw new VcenterSystemException(message + " Vcenter reported: " + taskMonitor.errorDescription); } else if (taskStatus == VcenterTaskMonitor.TaskStatus.TIMED_OUT) { throw new VcenterSystemException(message + " Task timed out."); } else { // task success but host did not enter maint mode - probably will not happen throw new VcenterSystemException(message); } } } } catch (VcenterSystemException e) { throw e; } catch (Exception e) { _log.error("enterMaintenanceMode exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } public void exitMaintenanceMode(String datacenterName, String clusterNameOrMoRef, String hostname) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { try { _log.info("Request to exit maintenance mode for host " + hostname + " in datacenter " + datacenterName + " cluster " + clusterNameOrMoRef); exitMaintenanceModeHost((HostSystem) createManagedEntityMap(datacenterName, clusterNameOrMoRef, hostname, true).get( "HostSystem")); } catch (VcenterSystemException | VcenterObjectNotFoundException | VcenterObjectConnectionException e) { throw e; } catch (Exception e) { _log.error("exitMaintenanceMode exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } private void exitMaintenanceModeHost(HostSystem hostSystem) throws VcenterSystemException { try { String hostname = hostSystem.getName(); if (hostSystem.getRuntime().isInMaintenanceMode()) { Integer operationTimeout = Integer.parseInt(propertyInfo.getProperty("vcenter_operation_timeout")); _log.info("Host " + hostname + " is in maintenance mode - Attempt to exit"); Task exitMaintenanceModeTask = hostSystem.exitMaintenanceMode(operationTimeout); VcenterTaskMonitor.TaskStatus taskStatus = (new VcenterTaskMonitor(operationTimeout)).monitor(exitMaintenanceModeTask); _log.info("After running exit maintenance mode task for host " + hostname + " the task result is " + taskStatus + " and host is in maintenance mode " + hostSystem.getRuntime().isInMaintenanceMode()); if (hostSystem.getRuntime().isInMaintenanceMode()) { _log.error("Host " + hostname + " failed to exit maintenance mode"); throw new VcenterSystemException("Host " + hostname + " failed to exit maintenance mode"); } } } catch (VcenterSystemException e) { throw e; } catch (Exception e) { _log.error("exitMaintenanceMode exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } public void removeHost(String datacenterName, String clusterNameOrMoRef, String hostname) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { try { _log.info("Request to remove host " + hostname + " to datacenter " + datacenterName + " cluster " + clusterNameOrMoRef); ClusterComputeResource clusterComputeResource = (ClusterComputeResource) createManagedEntityMap(datacenterName, clusterNameOrMoRef, null, false).get("ClusterComputeResource"); HostSystem hostSystem = findByHostname(clusterComputeResource, hostname); if (hostSystem == null) { _log.info("Host not found thus no delete necessary"); } else { // Check that host can be removed (either in maintenance mode or in a !poweredOn or !connected state try { checkHostConnectedPoweredOn(hostSystem); _log.info("Host " + hostname + " connected and powered on so now check maintenance mode"); if (!hostSystem.getRuntime().isInMaintenanceMode()) { _log.error("Host " + hostname + " must be in maintenance mode before deletion"); throw new VcenterSystemException("Host " + hostname + " must be in maintenance mode before deletion"); } } catch (VcenterObjectConnectionException e) { _log.info("Host is not connected and/or powered on so go ahead and remove without maintenance mode check"); } // Remove Integer hostOperationTimeout = Integer.parseInt(propertyInfo.getProperty("vcenter_host_operation_timeout")); VcenterTaskMonitor taskMonitor = new VcenterTaskMonitor(hostOperationTimeout); Task deleteHostTask = hostSystem.destroy_Task(); VcenterTaskMonitor.TaskStatus taskStatus = taskMonitor.monitor(deleteHostTask); // call blocks if (taskStatus == VcenterTaskMonitor.TaskStatus.SUCCESS) { _log.info("Delete host " + hostname + " task succeeded"); } else if (taskStatus == VcenterTaskMonitor.TaskStatus.ERROR) { String errorMessage = "Delete host " + hostname + " task failed - " + taskMonitor.errorDescription; _log.error(errorMessage); throw new VcenterSystemException(errorMessage); } else if (taskStatus == VcenterTaskMonitor.TaskStatus.TIMED_OUT) { _log.error("Delete host " + hostname + " task timed out at " + taskMonitor.progressPercent); throw new VcenterSystemException("Delete host " + hostname + " task timed out at " + taskMonitor.progressPercent); } else { // Should not execute - Just here in case someone ever added a new state so we catch it _log.error("Unknown task status encountered tracking delete host " + taskStatus); throw new VcenterSystemException("Unknown task status encountered tracking delete host " + taskStatus); } } } catch (VcenterSystemException | VcenterObjectNotFoundException | VcenterObjectConnectionException e) { throw e; } catch (Exception e) { _log.error("Exception removing host: " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } public String addHost(String datacenterName, String clusterNameOrMoRef, String hostname, String username, String password) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { try { _log.info("Request to add host " + hostname + " to datacenter " + datacenterName + " cluster " + clusterNameOrMoRef); ClusterComputeResource clusterComputeResource = (ClusterComputeResource) createManagedEntityMap(datacenterName, clusterNameOrMoRef, null, false).get("ClusterComputeResource"); HostSystem hostSystem = findByHostname(clusterComputeResource, hostname); if (hostSystem == null) { _log.info("Host " + hostname + " does not exist and will be added"); if (username == null || username.trim().equals("") || password == null || password.trim().equals("")) { _log.error("Username and/or password missing - Both required to add host to cluster"); throw new VcenterSystemException("Username and/or password missing - Both required to add host to cluster"); } HostConnectSpec hostConnectSpec = new HostConnectSpec(); hostConnectSpec.setHostName(hostname); hostConnectSpec.setUserName(username); hostConnectSpec.setPassword(password); hostConnectSpec.setSslThumbprint(getHostCertificate(hostname, username, password)); // ie // 1D:0C:63:FC:58:58:1C:66:F0:5B:C4:0B:F3:84:0E:27:E9:59:83:F7 _log.info("Attempt to add host " + hostname + " to " + datacenterName + "/" + clusterComputeResource.getName()); Integer hostOperationTimeout = Integer.parseInt(propertyInfo.getProperty("vcenter_host_operation_timeout")); Integer hostOperationTimeoutMillis = hostOperationTimeout * 1000; Integer retryCount = 1; Long startTimeMillis = System.currentTimeMillis(); Long cutoffTimeMillis = startTimeMillis + hostOperationTimeoutMillis; VcenterTaskMonitor taskMonitor = new VcenterTaskMonitor(hostOperationTimeout); Task addHostTask = clusterComputeResource.addHost_Task(hostConnectSpec, true, null, null); VcenterTaskMonitor.TaskStatus taskStatus = taskMonitor.monitor(addHostTask); // call blocks while ((System.currentTimeMillis() < cutoffTimeMillis) && taskStatus == VcenterTaskMonitor.TaskStatus.ERROR) { _log.info("Add host " + hostname + " retry error " + taskMonitor.errorDescription + " count " + retryCount); Thread.sleep(60000); // Retry is time based and if each retry executes very quickly (ie milliseconds) then we should // throttle and only retry every 60 seconds addHostTask = clusterComputeResource.addHost_Task(hostConnectSpec, true, null, null); taskStatus = taskMonitor.monitor(addHostTask); // call blocks retryCount++; } if (taskStatus == VcenterTaskMonitor.TaskStatus.SUCCESS) { _log.info("Add host " + hostname + " task succeeded - Attempt to find host in cluster"); hostSystem = findByHostname(clusterComputeResource, hostname); } else if (taskStatus == VcenterTaskMonitor.TaskStatus.ERROR) { String errorMessage = "Add host " + hostname + " task failed - " + taskMonitor.errorDescription; if (taskMonitor.errorDescription.contains("already exists.")) { errorMessage += " - Ensure adding host to correct cluster or remove host from its existing cluster"; } _log.error(errorMessage); throw new VcenterSystemException(errorMessage); } else if (taskStatus == VcenterTaskMonitor.TaskStatus.TIMED_OUT) { _log.error("Add host " + hostname + " task timed out at " + taskMonitor.progressPercent); throw new VcenterSystemException("Add host " + hostname + " task timed out at " + taskMonitor.progressPercent); } else { // Should not execute - Just here in case someone ever added a new state so we catch it _log.error("Unknown task status encountered tracking add host " + taskStatus); throw new VcenterSystemException("Unknown task status encountered tracking add host " + taskStatus); } trackHostTasks(hostSystem, hostOperationTimeout); // Only take host out of maintenance mode if it's being added. We don't want to exit maintenance mode on other hosts since // customer may have intentionally put it on that. exitMaintenanceModeHost(hostSystem); } // Some nice conveniences to reconnect and exit maintenance mode to ready the host for action reconnectHost(hostSystem); // Collect some details StringBuffer hostDetails = new StringBuffer(); hostDetails.append("Host ").append(datacenterName).append("/").append(clusterComputeResource.getName()).append("/") .append(hostname).append(" "); String os = hostSystem.getPropertyByPath("config.product.version").toString(); hostDetails.append("OS ").append(os).append(" "); String key = hostSystem.getMOR().getVal(); hostDetails.append("key ").append(key).append(" "); String connectionState = hostSystem.getRuntime().getConnectionState().toString(); hostDetails.append("Connection State ").append(connectionState).append(" "); String powerState = hostSystem.getRuntime().getPowerState().toString(); hostDetails.append("Power State ").append(powerState).append(" "); boolean maintenanceMode = hostSystem.getRuntime().isInMaintenanceMode(); hostDetails.append("Maintenance Mode ").append(maintenanceMode).append(" "); _log.info(hostDetails.toString()); return hostSystem.getMOR().getVal(); } catch (VcenterSystemException | VcenterObjectNotFoundException | VcenterObjectConnectionException e) { throw e; } catch (Exception e) { _log.error("Exception adding host: " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } private List<String> toString(List<VirtualMachine> virtualMachines) { List<String> virtualMachineNames = new ArrayList<String>(); if (virtualMachines == null || virtualMachines.isEmpty()) { return virtualMachineNames; } for (VirtualMachine virtualMachine : virtualMachines) { virtualMachineNames.add(virtualMachine.getName()); } return virtualMachineNames; } private List<String> getRunningVirtualMachines(String datacenterName, String clusterNameOrMoRef, String hostname, boolean runningOnly) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { try { _log.info("Request to get virtual machines for host " + hostname + " in datacenter " + datacenterName + " cluster " + clusterNameOrMoRef); return toString(getVirtualMachines( (HostSystem) createManagedEntityMap(datacenterName, clusterNameOrMoRef, hostname, true).get("HostSystem"), runningOnly)); } catch (VcenterSystemException | VcenterObjectNotFoundException | VcenterObjectConnectionException e) { throw e; } catch (Exception e) { _log.error("getVirtualMachines host exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } public List<String> getRunningVirtualMachines(String datacenterName, String clusterNameOrMoRef, String hostname) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { return getRunningVirtualMachines(datacenterName, clusterNameOrMoRef, hostname, true); } public List<String> getVirtualMachines(String datacenterName, String clusterNameOrMoRef, String hostname) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { return getRunningVirtualMachines(datacenterName, clusterNameOrMoRef, hostname, false); } private List<String> getVirtualMachines(String datacenterName, String clusterNameOrMoRef, boolean runningOnly) throws VcenterSystemException, VcenterObjectNotFoundException { try { _log.info("Request to get virtual machines for cluster " + clusterNameOrMoRef + " in datacenter " + datacenterName); return toString(getVirtualMachines( (ClusterComputeResource) createManagedEntityMap(datacenterName, clusterNameOrMoRef, null, false).get( "ClusterComputeResource"), runningOnly)); } catch (VcenterSystemException | VcenterObjectNotFoundException e) { throw e; } catch (Exception e) { _log.error("getVirtualMachines cluster exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } public List<String> getVirtualMachines(String datacenterName, String clusterNameOrMoRef) throws VcenterSystemException, VcenterObjectNotFoundException { return getVirtualMachines(datacenterName, clusterNameOrMoRef, false); } public List<String> getRunningVirtualMachines(String datacenterName, String clusterNameOrMoRef) throws VcenterSystemException, VcenterObjectNotFoundException { return getVirtualMachines(datacenterName, clusterNameOrMoRef, true); } private String toDetails(VirtualMachine virtualMachine) { // Collect some details StringBuffer vmDetails = new StringBuffer(); String name = virtualMachine.getName(); vmDetails.append("Name ").append(name); String key = virtualMachine.getMOR().getVal(); vmDetails.append("Key ").append(key); String powerState = virtualMachine.getRuntime().getPowerState().toString(); vmDetails.append("Power State ").append(powerState); boolean template = virtualMachine.getConfig().isTemplate(); vmDetails.append("Template ").append(template); return vmDetails.toString(); } private List<VirtualMachine> getVirtualMachines(ClusterComputeResource clusterComputeResource, boolean runningOnly) throws VcenterSystemException { try { List<VirtualMachine> virtualMachines = new ArrayList<VirtualMachine>(); String clusterName = clusterComputeResource.getName(); _log.info("Inspect cluster " + clusterName + " for virtual machines running only " + runningOnly); ResourcePool resourcePool = clusterComputeResource.getResourcePool(); if (resourcePool != null) { _log.info("Inspect resource pool " + resourcePool.getName() + " for virtual machines"); if (resourcePool.getVMs() != null) { for (VirtualMachine virtualMachine : resourcePool.getVMs()) { _log.info("Found virtual machine " + virtualMachine.getName() + " in resource pool " + resourcePool.getName()); _log.info(toDetails(virtualMachine)); if (runningOnly) { // Anything !poweredOff (poweredOn and suspended) will be considered running if (!virtualMachine.getRuntime().getPowerState().equals(VirtualMachinePowerState.poweredOff)) { virtualMachines.add(virtualMachine); } } else { virtualMachines.add(virtualMachine); } } } } _log.info("Cluster " + clusterName + " has " + virtualMachines.size() + " virtual machines"); return virtualMachines; } catch (Exception e) { _log.error("getVirtualMachines clusterComputeResource exception " + e); throw new VcenterSystemException("Error checking cluster for virtual machines"); } } private List<VirtualMachine> getVirtualMachines(HostSystem hostSystem, boolean runningOnly) throws VcenterSystemException { try { String hostname = hostSystem.getName(); _log.info("Inspect host " + hostname + " for virtual machines running only " + runningOnly); List<VirtualMachine> virtualMachines = new ArrayList<VirtualMachine>(); VirtualMachine[] hostVirtualMachines = hostSystem.getVms(); for (VirtualMachine virtualMachine : hostVirtualMachines) { _log.info("Found virtual machine " + virtualMachine.getName() + " on host " + hostname); _log.info(toDetails(virtualMachine)); if (runningOnly) { // Anything !poweredOff (poweredOn and suspended) will be considered running if (!virtualMachine.getRuntime().getPowerState().equals(VirtualMachinePowerState.poweredOff)) { virtualMachines.add(virtualMachine); } } else { virtualMachines.add(virtualMachine); } } _log.info("Host " + hostname + " has " + virtualMachines.size() + " virtual machines"); return virtualMachines; } catch (Exception e) { _log.error("getVirtualMachines hostSystem exception " + e); throw new VcenterSystemException("Error checking host for virtual machines"); } } public void checkHostConnectedPoweredOn(String datacenterName, String clusterNameOrMoRef, String hostname) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { try { _log.info("Request to check connected and powered on for host " + hostname + " in datacenter " + datacenterName + " cluster " + clusterNameOrMoRef); HostSystem hostSystem = (HostSystem) createManagedEntityMap(datacenterName, clusterNameOrMoRef, hostname, true).get( "HostSystem"); // checkHostConnectedPoweredOn is performed in this call } catch (VcenterSystemException | VcenterObjectNotFoundException | VcenterObjectConnectionException e) { throw e; } catch (Exception e) { _log.error("checkHostConnectedPoweredOn exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } private void checkHostConnectedPoweredOn(HostSystem hostSystem) throws VcenterObjectConnectionException { String hostname = hostSystem.getName(); if (hostSystem.getRuntime().getConnectionState() != HostSystemConnectionState.connected && hostSystem.getRuntime().getPowerState() != HostSystemPowerState.poweredOn) { _log.error("Host " + hostname + " is not connected and powered on"); throw new VcenterObjectConnectionException("Host " + hostname + " is not connected and powered on"); } } public void refreshRescanHostStorage(String datacenterName, String clusterNameOrMoRef, String hostname) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { try { _log.info("Request to check connected and powered on for host " + hostname + " in datacenter " + datacenterName + " cluster " + clusterNameOrMoRef); HostSystem hostSystem = (HostSystem) createManagedEntityMap(datacenterName, clusterNameOrMoRef, hostname, true).get( "HostSystem"); _log.info("Refresh and rescan storage before disk discovery on host " + hostname); hostSystem.getHostStorageSystem().rescanAllHba(); // expensive but needed to pickup any storage changes _log.info("Rescan HBAs complete"); hostSystem.getHostStorageSystem().refreshStorageSystem(); _log.info("Refresh storage system complete"); } catch (VcenterSystemException | VcenterObjectNotFoundException | VcenterObjectConnectionException e) { throw e; } catch (Exception e) { _log.error("refreshRescanStorage exception " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } public String createDatastore(String datacenterName, String clusterNameOrMoRef, String hostname, String volumeUuid, String datastoreName) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { try { _log.info("Request to create datastore on volume " + volumeUuid + " host " + hostname + " to datacenter " + datacenterName + " cluster " + clusterNameOrMoRef); HostSystem hostSystem = (HostSystem) createManagedEntityMap(datacenterName, clusterNameOrMoRef, hostname, true).get( "HostSystem"); if (volumeUuid == null || volumeUuid.trim().equals("")) { _log.error("Volume UUID not specified"); throw new VcenterSystemException("Volume UUID not specified"); } Datastore[] datastores = hostSystem.getDatastores(); if (datastores != null && datastores.length > 0) { _log.info("Check host " + hostname + " for existing datastore on volume " + volumeUuid); String specifiedVolumeDevicePath = null; HostStorageSystem hostStorageSystem = hostSystem.getHostStorageSystem(); HostStorageDeviceInfo hostStorageDeviceInfo = hostStorageSystem.getStorageDeviceInfo(); ScsiLun[] hostScsiLuns = hostStorageDeviceInfo.getScsiLun(); for (ScsiLun scsiLun : hostScsiLuns) { if (scsiLun instanceof HostScsiDisk) { HostScsiDisk hostScsiDisk = (HostScsiDisk) scsiLun; if (hostScsiDisk.getUuid().toLowerCase().contains(volumeUuid.toLowerCase())) { _log.info("Found disk " + hostScsiDisk.getUuid() + " on " + hostname + " for volume UUID " + volumeUuid); specifiedVolumeDevicePath = hostScsiDisk.getDevicePath(); break; } } } // We found the device path for the volume specified by the UUID above. Now possibly map that to a datastore to check if // datastore already exists. if (specifiedVolumeDevicePath != null) { for (Datastore datastore : datastores) { if (datastore.getInfo() instanceof VmfsDatastoreInfo) { VmfsDatastoreInfo vmfsDatastoreInfo = (VmfsDatastoreInfo) datastore.getInfo(); _log.info("Found datastore " + vmfsDatastoreInfo.getName() + " " + vmfsDatastoreInfo.getVmfs().getUuid()); String diskName = vmfsDatastoreInfo.getVmfs().getExtent()[0].getDiskName(); _log.info("Found datastore " + vmfsDatastoreInfo.getName() + " on disk " + diskName); String devicePath = "/vmfs/devices/disks/" + diskName; if (devicePath.equalsIgnoreCase(specifiedVolumeDevicePath)) { _log.info("Datastore " + vmfsDatastoreInfo.getName() + " " + devicePath + " " + datastore.getMOR().getVal() + " already present"); return datastore.getMOR().getVal(); } } } } } _log.info("Search for candidate disk via host " + hostname); HostDatastoreSystem hostDatastoreSystem = hostSystem.getHostDatastoreSystem(); HostScsiDisk[] hostScsiDisks = hostDatastoreSystem.queryAvailableDisksForVmfs(null); HostScsiDisk candidateHostScsiDisk = null; for (HostScsiDisk hostScsiDisk : hostScsiDisks) { _log.info("Found disk " + hostScsiDisk.getDevicePath() + " " + hostScsiDisk.getUuid()); if (hostScsiDisk.getUuid().toLowerCase().contains(volumeUuid.toLowerCase())) { candidateHostScsiDisk = hostScsiDisk; break; } } if (candidateHostScsiDisk == null) { _log.error("Disk " + volumeUuid + " not found - Ensure underlying storage properly configured and disk accessible to host"); throw new VcenterSystemException("Disk " + volumeUuid + " not found - Ensure underlying storage properly configured and disk accessible to host"); } String devicePath = candidateHostScsiDisk.getDevicePath(); _log.info("Create datastore via host " + hostname + " on disk " + devicePath); VmfsDatastoreOption[] vmfsDatastoreOption = hostDatastoreSystem.queryVmfsDatastoreCreateOptions(devicePath); VmfsDatastoreCreateSpec vmfsDatastoreCreateSpec = (VmfsDatastoreCreateSpec) vmfsDatastoreOption[0].getSpec(); vmfsDatastoreCreateSpec.getVmfs().setVolumeName(datastoreName); vmfsDatastoreCreateSpec.getVmfs().setBlockSizeMb(1); // TODO externalize Datastore datastore = null; try { datastore = hostDatastoreSystem.createVmfsDatastore(vmfsDatastoreCreateSpec); } catch (HostConfigFault hcf) { _log.info("HostConfigFault creating datastore on disk " + devicePath + " thus retry"); if (hcf.getFaultMessage() != null && hcf.getFaultMessage().length > 0 && hcf.getFaultMessage()[0] != null) { String errorMessage = hcf.getFaultMessage()[0].toString(); _log.error("HostConfigFault details are " + errorMessage); } datastore = hostDatastoreSystem.createVmfsDatastore(vmfsDatastoreCreateSpec); } if (datastore == null) { // Should not happen _log.error("Datastore null after create"); throw new VcenterSystemException("Error creating datastore"); } return datastore.getMOR().getVal(); } catch (VcenterSystemException | VcenterObjectNotFoundException | VcenterObjectConnectionException e) { throw e; } catch (Exception e) { _log.error("Exception creating datastore: " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } public void removeCluster(String datacenterName, String clusterNameOrMoRef) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { try { _log.info("Request to remove cluster in datacenter " + datacenterName + " cluster " + clusterNameOrMoRef); try { ClusterComputeResource clusterComputeResource = (ClusterComputeResource) createManagedEntityMap(datacenterName, clusterNameOrMoRef, null, false).get("ClusterComputeResource"); String clusterName = clusterComputeResource.getName(); _log.info("Attempt to delete cluster " + clusterName); // Remove Integer clusterOperationTimeout = Integer.parseInt(propertyInfo.getProperty("vcenter_operation_timeout")); VcenterTaskMonitor taskMonitor = new VcenterTaskMonitor(clusterOperationTimeout); Task deleteClusterTask = clusterComputeResource.destroy_Task(); VcenterTaskMonitor.TaskStatus taskStatus = taskMonitor.monitor(deleteClusterTask); // call blocks if (taskStatus == VcenterTaskMonitor.TaskStatus.SUCCESS) { _log.info("Delete cluster " + clusterName + " task succeeded"); } else if (taskStatus == VcenterTaskMonitor.TaskStatus.ERROR) { String errorMessage = "Delete cluster " + clusterName + " task failed - " + taskMonitor.errorDescription; _log.error(errorMessage); throw new VcenterSystemException(errorMessage); } else if (taskStatus == VcenterTaskMonitor.TaskStatus.TIMED_OUT) { _log.error("Delete cluster " + clusterName + " task timed out at " + taskMonitor.progressPercent); throw new VcenterSystemException("Delete cluster " + clusterName + " task timed out at " + taskMonitor.progressPercent); } else { // Should not execute - Just here in case someone ever added a new state so we catch it _log.error("Unknown task status encountered tracking delete cluster " + taskStatus); throw new VcenterSystemException("Unknown task status encountered tracking delete cluster " + taskStatus); } } catch (VcenterObjectNotFoundException e) { _log.info("Cluster not found thus no delete necessary"); } } catch (VcenterSystemException | VcenterObjectNotFoundException | VcenterObjectConnectionException e) { throw e; } catch (Exception e) { _log.error("Exception removing cluster: " + e); throw new VcenterSystemException(e.getLocalizedMessage()); } } /** * Verifies if the host can see the volume, if so then check for VMs (powered on/off) * on the datastore identified for the given volume wwn. * * @param datacenterName {@link String} name of the dataCenter * @param clusterNameOrMoRef {@link String} name of the cluster * @param hostName {@link String} name of the host * @param volumewwn {@link String} volume wwn * @return true when there are any VMs on the datastore identified by the volume wwn, otherwise false * @throws VcenterSystemException * @throws VcenterObjectNotFoundException * @throws VcenterObjectConnectionException */ public boolean checkVMsOnHostVolume(String datacenterName, String clusterNameOrMoRef, String hostName, String volumewwn) throws VcenterSystemException, VcenterObjectNotFoundException, VcenterObjectConnectionException { boolean isVMsPresent = false; try { _log.info("Request to check VMs on volume " + volumewwn + " host " + hostName + " to datacenter " + datacenterName + " cluster " + clusterNameOrMoRef); HostSystem hostSystem = (HostSystem) createManagedEntityMap(datacenterName, clusterNameOrMoRef, hostName, false).get("HostSystem"); if (volumewwn == null || volumewwn.trim().equals("")) { _log.error("Volume UUID not specified"); throw new VcenterSystemException("Volume UUID not specified"); } Datastore[] datastores = hostSystem.getDatastores(); if (datastores != null && datastores.length > 0) { _log.info("Found {} datastores for host {}", datastores.length, hostName); String specifiedVolumeDevicePath = null; HostStorageSystem hostStorageSystem = hostSystem.getHostStorageSystem(); HostStorageDeviceInfo hostStorageDeviceInfo = hostStorageSystem.getStorageDeviceInfo(); ScsiLun[] hostScsiLuns = hostStorageDeviceInfo.getScsiLun(); for (ScsiLun scsiLun : hostScsiLuns) { if (scsiLun instanceof HostScsiDisk) { HostScsiDisk hostScsiDisk = (HostScsiDisk) scsiLun; // Check if host is able to see the specified volume if (hostScsiDisk.getUuid().toLowerCase().contains(volumewwn.toLowerCase())) { _log.info("Found disk " + hostScsiDisk.getUuid() + " on " + hostName + " for volume UUID " + volumewwn); specifiedVolumeDevicePath = hostScsiDisk.getDevicePath(); break; } } } if (specifiedVolumeDevicePath != null) { Datastore bootVolDatastore = null; for (Datastore datastore : datastores) { _log.info("Find existing datastore on volume " + volumewwn + " for host " + hostName); if (datastore.getInfo() instanceof VmfsDatastoreInfo) { VmfsDatastoreInfo vmfsDatastoreInfo = (VmfsDatastoreInfo) datastore.getInfo(); String diskName = vmfsDatastoreInfo.getVmfs().getExtent()[0].getDiskName(); if (specifiedVolumeDevicePath.contains(diskName) && diskName.contains(volumewwn.toLowerCase())) { _log.info("Found datastore " + vmfsDatastoreInfo.getName() + " on disk " + diskName); bootVolDatastore = datastore; break; } } } if (bootVolDatastore != null) { if (CollectionUtils.isNotEmpty(Arrays.asList(bootVolDatastore.getVms()))) { isVMsPresent = true; _log.info("Found {} VMs on the datastore {}", bootVolDatastore.getVms().length, bootVolDatastore.getName()); } else { _log.info("No VMs found on datastore {}", bootVolDatastore.getName()); } } else { _log.warn("Could not find datastore for host {} on volume wwn {}", hostName, volumewwn); } } else { _log.warn("Could not find disk on host {} for volume UUID {}", hostName, volumewwn); } } else { _log.info("No datastores found for host {}, hence inferring that no VMs are present on the given volume wwn {}", hostName, volumewwn); } } catch (VcenterSystemException | VcenterObjectNotFoundException | VcenterObjectConnectionException e) { _log.error("Vcenter exception checkVMsOnHostVolume : {}", e); throw e; } catch (Exception e) { _log.error("Exception checkVMsOnHostVolume : {}", e); throw new VcenterSystemException(e.getLocalizedMessage()); } return isVMsPresent; } }