/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package com.emc.storageos.computesystemcontroller.impl.adapter; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import com.emc.storageos.computesystemcontroller.exceptions.CompatibilityException; import com.emc.storageos.computesystemcontroller.exceptions.ComputeSystemControllerException; import com.emc.storageos.computesystemcontroller.impl.HostToComputeElementMatcher; import com.emc.storageos.computesystemcontroller.impl.ComputeSystemHelper; import com.emc.storageos.computesystemcontroller.impl.DiscoveryStatusUtils; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.URIUtil; import com.emc.storageos.db.client.model.Cluster; import com.emc.storageos.db.client.model.DiscoveredDataObject.CompatibilityStatus; import com.emc.storageos.db.client.model.DiscoveredDataObject.DataCollectionJobStatus; import com.emc.storageos.db.client.model.DiscoveredDataObject.RegistrationStatus; import com.emc.storageos.db.client.model.DiscoveredSystemObject; import com.emc.storageos.db.client.model.Host; import com.emc.storageos.db.client.model.Host.HostType; import com.emc.storageos.db.client.model.HostInterface; import com.emc.storageos.db.client.model.Initiator; import com.emc.storageos.db.client.model.Vcenter; import com.emc.storageos.db.client.model.VcenterDataCenter; import com.emc.storageos.db.client.model.util.EventUtils; import com.emc.storageos.db.client.util.CommonTransformerFunctions; import com.emc.storageos.db.client.util.NullColumnValueGetter; import com.emc.storageos.security.authorization.BasePermissionsHelper; import com.google.common.collect.Collections2; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.iwave.ext.vmware.VCenterAPI; import com.iwave.ext.vmware.VcenterVersion; import com.vmware.vim25.AboutInfo; import com.vmware.vim25.HostHardwareInfo; import com.vmware.vim25.HostSystemConnectionState; import com.vmware.vim25.InvalidLogin; import com.vmware.vim25.mo.ClusterComputeResource; import com.vmware.vim25.mo.Datacenter; import com.vmware.vim25.mo.HostSystem; /** * Discovery adapter for vCenters. * * @author jonnymiller */ @Component public class VcenterDiscoveryAdapter extends EsxHostDiscoveryAdapter { @Override public boolean isSupportedTarget(String targetId) { return URIUtil.isType(URI.create(targetId), Vcenter.class); } @Override public void discoveryFailure(DiscoveredSystemObject target, String compatibilityStatus, String errorMessage) { super.discoveryFailure(target, compatibilityStatus, errorMessage); Vcenter vcenter = getModelClient().vcenters().findById(target.getId()); Iterable<VcenterDataCenter> dataCenters = getModelClient().datacenters().findByVCenter(vcenter.getId(), true); for (VcenterDataCenter dataCenter : dataCenters) { Iterable<Host> hosts = getModelClient().hosts().findByVcenterDatacenter(dataCenter.getId()); for (Host host : hosts) { host.setDiscoveryStatus(DataCollectionJobStatus.ERROR.name()); host.setLastDiscoveryRunTime(System.currentTimeMillis()); host.setCompatibilityStatus(compatibilityStatus); host.setLastDiscoveryStatusMessage("vCenter Discovery Failed: " + errorMessage); save(host); } } } @Override public void discoverTarget(String targetId) { Vcenter vcenter = getModelClient().vcenters().findById(targetId); discoverVCenter(vcenter); } public void discoverVCenter(Vcenter vcenter) { DiscoveryProcessor processor = new DiscoveryProcessor(vcenter); VcenterVersion version = getVersion(vcenter); vcenter.setOsVersion(version.toString()); if (getVersionValidator().isValidVcenterVersion(version)) { List<HostStateChange> changes = Lists.newArrayList(); List<URI> deletedHosts = Lists.newArrayList(); List<URI> deletedClusters = Lists.newArrayList(); Set<URI> discoveredHosts = Sets.newHashSet(); processor.discover(changes, deletedHosts, deletedClusters, discoveredHosts); matchHostsToComputeElements(discoveredHosts) ; deletedHosts.removeAll(discoveredHosts); processor.setCompatibilityStatus(CompatibilityStatus.COMPATIBLE.name()); // only update registration status of hosts if the vcenter is unregistered // to ensure newly discovered hosts are marked as unregistered if (vcenter.getRegistrationStatus().equals(RegistrationStatus.UNREGISTERED.toString())) { processor.setRegistrationStatus(vcenter.getRegistrationStatus()); } save(vcenter); processHostChanges(changes, deletedHosts, deletedClusters, true); } else { processor.setCompatibilityStatus(CompatibilityStatus.INCOMPATIBLE.name()); save(vcenter); throw ComputeSystemControllerException.exceptions.incompatibleHostVersion( "Vcenter", version.toString(), getVersionValidator().getVcenterMinimumVersion(false).toString()); } } private void matchHostsToComputeElements(Set<URI> hostIds) { HostToComputeElementMatcher.matchHostsToComputeElements(getDbClient(),hostIds); } @Override public String getErrorMessage(Throwable t) { Throwable rootCause = getRootCause(t); if (rootCause instanceof InvalidLogin) { return "Login failed, invalid username or password"; } else if (rootCause instanceof RemoteException) { String message = rootCause.getMessage(); if (StringUtils.contains(message, "java.net.UnknownHostException: ")) { return "Unknown host: " + StringUtils.substringAfter(message, "java.net.UnknownHostException: "); } else if (StringUtils.contains(message, "java.net.ConnectException: ")) { return "Error connecting: " + StringUtils.substringAfter(message, "java.net.ConnectException: "); } else if (StringUtils.contains(message, "java.net.NoRouteToHostException: ")) { return "No route to host: " + StringUtils.substringAfter(message, "java.net.NoRouteToHostException: "); } else if (StringUtils.startsWith(message, "VI SDK invoke exception:")) { return StringUtils.substringAfter(message, "VI SDK invoke exception:"); } } return super.getErrorMessage(t); } public VcenterVersion getVersion(Vcenter vcenter) { VCenterAPI api = createVCenterAPI(vcenter); return api.getVcenterVersion(); } private Iterable<VcenterDataCenter> getDatacenters(Vcenter vcenter) { return getModelClient().datacenters().findByVCenter(vcenter.getId(), true); } private VcenterDataCenter getOrCreateDataCenter(List<VcenterDataCenter> datacenters, String name) { return getOrCreate(VcenterDataCenter.class, datacenters, name); } private Iterable<Cluster> getClusters(VcenterDataCenter datacenter) { return getModelClient().clusters().findByDatacenter(datacenter.getId(), true); } private Cluster getOrCreateCluster(List<Cluster> clusters, String name) { return getOrCreate(Cluster.class, clusters, name); } private Iterable<Host> getHosts(VcenterDataCenter datacenter) { return getModelClient().esxHosts().findByDatacenter(datacenter.getId(), true); } private VcenterDataCenter findDatacenterByExternalId(List<VcenterDataCenter> dataCenters, String extId) { if (extId != null) { for (VcenterDataCenter dataCenter : dataCenters) { if (extId.equals(dataCenter.getExternalId())) { return dataCenter; } } } return null; } private Cluster findClusterByExternalId(List<Cluster> clusters, String extId) { for (Cluster cluster : clusters) { if (extId.equals(cluster.getExternalId())) { return cluster; } } return null; } private Iterable<Host> getHosts(Cluster cluster) { return getModelClient().hosts().findByCluster(cluster.getId(), true); } private void deleteDatacenters(Iterable<VcenterDataCenter> datacenters, List<URI> deletedHosts, List<URI> deletedClusters) { for (VcenterDataCenter datacenter : datacenters) { boolean containsHosts = false; boolean clustersInUse = false; for (Cluster cluster : getClusters(datacenter)) { deletedClusters.add(cluster.getId()); } for (Host host : getHosts(datacenter)) { deletedHosts.add(host.getId()); containsHosts = true; } for (Cluster cluster : getClusters(datacenter)) { URI clusterId = cluster.getId(); List<URI> hostUris = ComputeSystemHelper.getChildrenUris(dbClient, clusterId, Host.class, "cluster"); if (hostUris.isEmpty() && !ComputeSystemHelper.isClusterInExport(dbClient, clusterId) && EventUtils.findAffectedResourcePendingEvents(dbClient, clusterId).isEmpty()) { info("Deactivating Cluster: " + clusterId); ComputeSystemHelper.doDeactivateCluster(dbClient, cluster); } else { info("Unable to delete cluster " + clusterId); clustersInUse = true; } } // delete datacenters that don't contain any clusters or hosts, don't have any exports, and don't have any pending events if (!containsHosts && !clustersInUse && !ComputeSystemHelper.isDataCenterInUse(dbClient, datacenter.getId()) && EventUtils.findAffectedResourcePendingEvents(dbClient, datacenter.getId()).isEmpty()) { info("Deactivating Datacenter: " + datacenter.getId()); ComputeSystemHelper.doDeactivateVcenterDataCenter(dbClient, datacenter); } else { info("Unable to delete datacenter " + datacenter.getId()); } } } public static VCenterAPI createVCenterAPI(Vcenter vcenter) { int port = vcenter.getPortNumber() != null ? vcenter.getPortNumber() : 443; URL url; try { url = new URL("https", vcenter.getIpAddress(), port, "/sdk"); } catch (MalformedURLException e) { throw new RuntimeException(e.getMessage()); } String username = vcenter.getUsername(); String password = vcenter.getPassword(); return new VCenterAPI(url, username, password); } /** * Discovery processor for VCenters. * * @author jonnymiller */ protected class DiscoveryProcessor { private Vcenter vcenter; private VCenterAPI vcenterAPI; public DiscoveryProcessor(Vcenter vcenter) { this.vcenter = vcenter; } public void discover(List<HostStateChange> changes, List<URI> deletedHosts, List<URI> deletedClusters, Set<URI> discoveredHosts) { vcenterAPI = createVCenterAPI(vcenter); try { AboutInfo aboutInfo = vcenterAPI.getAboutInfo(); if (!StringUtils.equals(aboutInfo.getApiType(), VCenterAPI.VCENTER_API_TYPE)) { throw new CompatibilityException("Not a vCenter (Type: " + aboutInfo.getFullName() + ")"); } checkDuplicateVcenter(vcenter, aboutInfo.getInstanceUuid()); vcenter.setNativeGuid(aboutInfo.getInstanceUuid()); discoverDatacenters(changes, deletedHosts, deletedClusters, discoveredHosts); } finally { vcenterAPI.logout(); } } private VcenterDataCenter findOrCreateDataCenter(List<VcenterDataCenter> datacenters, Datacenter sourceDatacenter) { VcenterDataCenter dataCenter = findDatacenterByExternalId(datacenters, sourceDatacenter.getMOR().getVal()); if (dataCenter != null) { datacenters.remove(dataCenter); } else { dataCenter = getOrCreateDataCenter(datacenters, sourceDatacenter.getName()); } return dataCenter; } private void discoverDatacenters(List<HostStateChange> changes, List<URI> deletedHosts, List<URI> deletedClusters, Set<URI> discoveredHosts) { List<VcenterDataCenter> oldDatacenters = new ArrayList<VcenterDataCenter>(); Iterables.addAll(oldDatacenters, getDatacenters(vcenter)); for (Datacenter sourceDatacenter : vcenterAPI.listAllDatacenters()) { VcenterDataCenter targetDatacenter = findOrCreateDataCenter(oldDatacenters, sourceDatacenter); discoverDatacenter(sourceDatacenter, targetDatacenter, changes, deletedHosts, deletedClusters, discoveredHosts); } deleteDatacenters(oldDatacenters, deletedHosts, deletedClusters); } private Cluster findClusterHostUuid(ClusterComputeResource cluster) { String hostUuid = null; HostSystem[] hosts = cluster.getHosts(); if (hosts != null) { for (HostSystem host : hosts) { HostHardwareInfo hw = host.getHardware(); if (hw != null && hw.systemInfo != null && StringUtils.isNotBlank(hw.systemInfo.uuid)) { hostUuid = hw.systemInfo.uuid; break; } } } if (hostUuid != null) { Host host = findHostByUuid(hostUuid); if (host != null && !NullColumnValueGetter.isNullURI(host.getCluster())) { return getModelClient().clusters().findById(host.getCluster()); } } return null; } private Cluster findClusterByName(URI tenant, String name) { for (Cluster cluster : getModelClient().clusters().findByLabel(tenant.toString(), name, true)) { // the above findByLabel() method actually uses findByPrefix() which can result in partial matches if (name.equals(cluster.getLabel())) { return cluster; } } return null; } private void discoverDatacenter(Datacenter source, VcenterDataCenter target, List<HostStateChange> changes, List<URI> deletedHosts, List<URI> deletedClusters, Set<URI> discoveredHosts) { info("processing datacenter %s", source.getName()); target.setVcenter(vcenter.getId()); setVcenterDataCenterTenant(target); target.setExternalId(source.getMOR().getVal()); target.setLabel(source.getName()); save(target); List<Cluster> oldClusters = new ArrayList<Cluster>(); Iterables.addAll(oldClusters, getClusters(target)); List<Cluster> newClusters = Lists.newArrayList(); reconcileClusters(source, target, oldClusters, newClusters); List<Host> oldHosts = new ArrayList<Host>(); Iterables.addAll(oldHosts, getHosts(target)); for (HostSystem sourceHost : vcenterAPI.listHostSystems(source)) { Host targetHost = null; HostHardwareInfo hw = sourceHost.getHardware(); String uuid = null; if (hw != null && hw.systemInfo != null && StringUtils.isNotBlank(hw.systemInfo.uuid)) { // try finding host by UUID uuid = hw.systemInfo.uuid; targetHost = findHostByUuid(uuid); } if (targetHost == null) { if (findHostByLabel(oldHosts, sourceHost.getName()) != null) { targetHost = getOrCreateHost(oldHosts, sourceHost.getName()); } else { Host existingHost = findExistingHost(sourceHost); if (existingHost != null) { targetHost = existingHost; } else { targetHost = getOrCreateHost(oldHosts, sourceHost.getName()); } } } else { for (int i = 0; i < oldHosts.size(); i++) { if (oldHosts.get(i).getId().equals(targetHost.getId())) { oldHosts.remove(i); break; } } } String bios = null;; if (hw != null && hw.biosInfo != null && StringUtils.isNotBlank(hw.biosInfo.biosVersion)) { bios = hw.biosInfo.biosVersion; } if (deletedHosts != null && deletedHosts.contains(target.getId())) { deletedHosts.remove(target.getId()); info("Removing host " + target.getId() + " from deletedHosts. It may have been rediscovered in a different datacenter"); } DiscoveryStatusUtils.markAsProcessing(getModelClient(), targetHost); try { discoverHost(source, sourceHost, uuid, bios, target, targetHost, newClusters, changes); discoveredHosts.add(targetHost.getId()); DiscoveryStatusUtils.markAsSucceeded(getModelClient(), targetHost); } catch (RuntimeException e) { warn(e, "Problem discovering host %s", targetHost.getLabel()); DiscoveryStatusUtils.markAsFailed(getModelClient(), targetHost, e.getMessage(), e); } } for (Host oldHost : oldHosts) { if (!discoveredHosts.contains(oldHost.getId())) { info("Unable to discover host %s. Marking as failed discovery.", oldHost.getId()); DiscoveryStatusUtils.markAsFailed(getModelClient(), oldHost, "Unable to discover host. Host may be disconnected.", null); } } Collection<URI> oldClusterIds = Lists.newArrayList(Collections2.transform(oldClusters, CommonTransformerFunctions.fctnDataObjectToID())); deletedClusters.addAll(oldClusterIds); Collection<URI> oldHostIds = Lists.newArrayList(Collections2.transform(oldHosts, CommonTransformerFunctions.fctnDataObjectToID())); deletedHosts.addAll(oldHostIds); } /** * Get all clusters for the datacenter. * Sort them by host count - descending. The reason for this - if vcenter has more than one * cluster that matches Vipr cluster, then the one with most hosts will be matched first. * Try find the cluster in Vipr by first by vcenter cluster ID, then by name, then by host membership. * If not found create new cluster. */ private void reconcileClusters(Datacenter source, VcenterDataCenter target, List<Cluster> oldClusters, List<Cluster> newClusters) { List<ClusterHolder> allClusters = new ArrayList<ClusterHolder>(); // get all clusters List<ClusterComputeResource> vcClusters = vcenterAPI.listClusters(source); // put clusters in a sortable list for (ClusterComputeResource vcCluster : vcClusters) { allClusters.add(new ClusterHolder(vcCluster, vcCluster.getHosts().length)); } // sort clusters so that those with most host will be processed first Collections.sort(allClusters); // process clusters - try finding them first; if can't, create new one for (ClusterHolder clusterHolder : allClusters) { ClusterComputeResource vcCluster = clusterHolder.cluster; String vcenterClusterId = vcCluster.getMOR().getVal(); info("processing cluster %s %s", vcCluster.getName(), vcenterClusterId); // find this cluster Cluster targetCluster = findCluster(oldClusters, vcCluster, target.getId()); if (targetCluster == null) { // did not find it, have to create a new one info("creating new cluster %s", vcCluster.getName()); targetCluster = getOrCreateCluster(oldClusters, vcCluster.getName()); } targetCluster.setLabel(vcCluster.getName()); targetCluster.setTenant(target.getTenant()); targetCluster.setVcenterDataCenter(target.getId()); targetCluster.setExternalId(vcenterClusterId); save(targetCluster); ComputeSystemHelper.updateInitiatorClusterName(dbClient, targetCluster.getId()); newClusters.add(targetCluster); } } /** * This tries to find Cluster using this algorithm: * 1) Look among existing clusters using the vcenter cluster ID. * 2) Look among existing clusters by name. * 3) Look among clusters belonging to this tenant, that don't belong to any datacenter. * 4) Find by host UUID: * a) Take any host UUID. * b) Find matching host in Vipr. * c) Find Cluster that host is in. * d) Return that Cluster if its externalId is null - because otherwise it is related to another cluster. */ private Cluster findCluster(List<Cluster> oldClusters, ClusterComputeResource vcCluster, URI vCenterDataCenterId) { // 1) find cluster by vcenter cluster id Cluster targetCluster = findClusterByExternalId(oldClusters, vcCluster.getMOR().getVal()); info("find by vcenter cluster id %s", targetCluster == null ? "NULL" : targetCluster.getLabel()); if (targetCluster == null) { // 2) try finding by name among the existing clusters targetCluster = findModelByLabel(oldClusters, vcCluster.getName()); info("find by name in dc %s", targetCluster == null ? "NULL" : targetCluster.getLabel()); } if (targetCluster != null) { // if found among old clusters, then remove it from the list oldClusters.remove(targetCluster); } if (targetCluster == null) { // 3) try finding by name in the tenant, must not belong to any datacenter targetCluster = getModelClient().clusters().findClusterByNameAndDatacenter(vCenterDataCenterId, vcCluster.getName(), true); info("find by name in tenant %s", targetCluster == null ? "NULL" : targetCluster.getLabel()); if (targetCluster != null && !NullColumnValueGetter.isNullURI(targetCluster.getVcenterDataCenter())) { // can't use this one info("found, but can't use it"); targetCluster = null; } } if (targetCluster == null) { // 4) try finding by hosts targetCluster = findClusterHostUuid(vcCluster); info("find by host uuid %s", targetCluster == null ? "NULL" : targetCluster.getLabel()); if (targetCluster != null && NullColumnValueGetter.isNotNullValue(targetCluster.getExternalId())) { // can't use this one info("found, but can't use it, it is related to another cluster"); targetCluster = null; } } return targetCluster; } private void discoverHost(Datacenter sourceDatacenter, HostSystem source, String uuid, String bios, VcenterDataCenter targetDatacenter, Host target, List<Cluster> clusters, List<HostStateChange> changes) { URI oldDatacenterURI = target.getVcenterDataCenter(); URI newDatacenterURI = targetDatacenter.getId(); boolean isDatacenterChanged = false; info("Discovering host " + target.getLabel() + " (" + target.getId() + ")"); if (NullColumnValueGetter.isNullURI(oldDatacenterURI) || (!NullColumnValueGetter.isNullURI(newDatacenterURI) && newDatacenterURI.toString().equalsIgnoreCase(oldDatacenterURI.toString()))) { info("setting vCenter datacenter to " + targetDatacenter.getLabel() + " (" + targetDatacenter.getId() + ") and tenant to " + targetDatacenter.getTenant() + " for host " + target.getLabel()); target.setVcenterDataCenter(targetDatacenter.getId()); target.setTenant(targetDatacenter.getTenant()); } else { isDatacenterChanged = true; } target.setDiscoverable(true); if (target.getId() == null) { target.setRegistrationStatus(RegistrationStatus.REGISTERED.toString()); } if (!target.getLabel().equals(source.getName())) { target.setLabel(source.getName()); } // Configure the cluster String clusterName = getClusterName(source); URI oldClusterURI = target.getCluster(); Cluster cluster = null; if (clusterName != null) { cluster = findModelByLabel(clusters, clusterName); } if (target.getType() == null || StringUtils.equalsIgnoreCase(target.getType(), HostType.Other.toString()) || StringUtils.equalsIgnoreCase(target.getType(), HostType.No_OS.toString())) { target.setType(Host.HostType.Esx.name()); } target.setHostName(target.getLabel()); target.setOsVersion(source.getConfig().getProduct().getVersion()); if(bios != null) { target.setBios(bios); } if (uuid != null) { target.setUuid(uuid); } save(target); // Only attempt to update ip interfaces or initiators for connected hosts HostSystemConnectionState connectionState = getConnectionState(source); info("Connection status for host %s is %s", target.forDisplay(), connectionState); if (connectionState == HostSystemConnectionState.connected) { // discover initiators List<Initiator> oldInitiators = new ArrayList<Initiator>(); List<Initiator> addedInitiators = new ArrayList<Initiator>(); discoverConnectedHostInitiators(source, target, oldInitiators, addedInitiators); URI targetCluster = cluster != null ? cluster.getId() : NullColumnValueGetter.getNullURI(); boolean isClusterChanged = NullColumnValueGetter.isNullURI(oldClusterURI) ? !NullColumnValueGetter.isNullURI(targetCluster) : targetCluster != null && !oldClusterURI.toString().equals(targetCluster.toString()); if (!oldInitiators.isEmpty() || !addedInitiators.isEmpty() || isClusterChanged || isDatacenterChanged) { changes.add(new HostStateChange(target, oldClusterURI, targetCluster, oldInitiators, addedInitiators, oldDatacenterURI, newDatacenterURI)); } } else { if (connectionState == HostSystemConnectionState.disconnected) { throw new IllegalStateException("Host is disconnected"); } else if (connectionState == HostSystemConnectionState.notResponding) { throw new IllegalStateException("Host is not responding"); } else { throw new IllegalStateException("Could not determine host connection state"); } } } protected String getClusterName(HostSystem host) { if (host.getParent() instanceof ClusterComputeResource) { return host.getParent().getName(); } else { return null; } } protected void setRegistrationStatus(String status) { Iterable<VcenterDataCenter> datacenters = getDatacenters(vcenter); for (VcenterDataCenter datacenter : datacenters) { setRegistrationStatus(datacenter, status); } } protected void setRegistrationStatus(VcenterDataCenter datacenter, String status) { Iterable<Host> hosts = getHosts(datacenter); for (Host host : hosts) { setRegistrationStatus(host, status); } } protected void setRegistrationStatus(Host host, String status) { host.setRegistrationStatus(status); save(host); setRegistrationStatus(getInitiators(host), status); setRegistrationStatus(getIpInterfaces(host), status); } protected void setRegistrationStatus(Iterable<? extends HostInterface> hostInterfaces, String status) { for (HostInterface hostInterface : hostInterfaces) { hostInterface.setRegistrationStatus(status); save(hostInterface); } } protected void setCompatibilityStatus(String status) { vcenter.setCompatibilityStatus(status); save(vcenter); Iterable<VcenterDataCenter> datacenters = getDatacenters(vcenter); for (VcenterDataCenter datacenter : datacenters) { setCompatibilityStatus(datacenter, status); } } protected void setCompatibilityStatus(VcenterDataCenter datacenter, String status) { Iterable<Host> hosts = getHosts(datacenter); for (Host host : hosts) { setCompatibilityStatus(host, status); } } protected void setCompatibilityStatus(Host host, String status) { host.setCompatibilityStatus(status); save(host); } /** * This just to allow sorting of clusters by host count. */ class ClusterHolder implements Comparable<ClusterHolder> { public ClusterComputeResource cluster; public int hostCount; public ClusterHolder(ClusterComputeResource c, int num) { cluster = c; hostCount = num; } @Override public int compareTo(ClusterHolder arg) { return arg.hostCount - this.hostCount; } } /** * Sets the vCenterDataCenter's tenant based on the vCenter's tenant. * If the vCenter is created by the tenant admin and if vCenter is shared * with only one tenant and vCenterDataCenter does not belong to any tenant * already then set the vCenter's tenant to the vCenterDataCenter and set to * null if vCenter is shared with multiple tenants. * If the vCenterDataCenter is already assigned to a tenant but the vCenter * is shared with that tenant anymore then reset the vCenterDataCenters tenant * to null. * * @param target vCenterDataCenter to be updated with the new tenant information. */ private void setVcenterDataCenterTenant(VcenterDataCenter target) { if (NullColumnValueGetter.isNullURI(target.getTenant())) { if (vcenter.getCascadeTenancy()) { target.setTenant(BasePermissionsHelper.getTenant(vcenter.getAcls())); } else { target.setTenant(NullColumnValueGetter.getNullURI()); } } else { Set<URI> vCenterTenants = BasePermissionsHelper.getUsageURIsFromAcls(vcenter.getAcls()); if (CollectionUtils.isEmpty(vCenterTenants) || !vCenterTenants.contains(target.getTenant())) { target.setTenant(NullColumnValueGetter.getNullURI()); } } getLog().debug("vCenterDataCenter {} is updated with tenant {}", target.getLabel(), target.getTenant()); } } public void setDbCLient(DbClient dbClient) { super.setDbClient(dbClient); } protected void checkDuplicateVcenter(Vcenter vcenter, String nativeGuid) { if (nativeGuid != null && !nativeGuid.isEmpty()) { for (Vcenter existingVcenter : modelClient.vcenters().findByNativeGuid(nativeGuid, true)) { if (!existingVcenter.getId().equals(vcenter.getId())) { ComputeSystemControllerException ex = ComputeSystemControllerException.exceptions.duplicateSystem("vCenter", existingVcenter.getLabel()); DiscoveryStatusUtils.markAsFailed(modelClient, vcenter, ex.getMessage(), ex); throw ex; } } } } /** * Sets properties pertaining to the {@link Initiator} * * @param initiator {@link Initiator} * @param host {@link Host} */ protected void setInitiatorHost(Initiator initiator, Host host) { setHostInterfaceRegistrationStatus(initiator, host); initiator.setHost(host.getId()); initiator.setHostName(host.getHostName()); Cluster cluster = getCluster(host); initiator.setClusterName(cluster != null ? cluster.getLabel() : ""); } protected Cluster getCluster(Host host) { if (host.getCluster() != null) { return get(Cluster.class, host.getCluster()); } else { return null; } } }