/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package com.emc.storageos.computesystemcontroller.impl; import java.net.URI; import java.util.List; import javax.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.emc.storageos.computesystemcontroller.exceptions.CompatibilityException; import com.emc.storageos.computesystemcontroller.exceptions.ComputeSystemControllerException; import com.emc.storageos.coordinator.client.service.CoordinatorClient; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.ModelClient; import com.emc.storageos.db.client.impl.ModelClientImpl; import com.emc.storageos.db.client.model.DiscoveredDataObject; import com.emc.storageos.db.client.model.DiscoveredSystemObject; import org.apache.curator.framework.recipes.locks.InterProcessLock; /** * Discovery engine that will discover Hosts and vCenters */ @Component public class ComputeSystemDiscoveryEngine { private static final Logger LOG = LoggerFactory.getLogger(ComputeSystemDiscoveryEngine.class); @Autowired private List<ComputeSystemDiscoveryAdapter> discoveryAdapters; private CoordinatorClient coordinatorClient; private DbClient dbClient; private ModelClient modelClient; public void setCoordinatorClient(CoordinatorClient client) { this.coordinatorClient = client; this.shareCoordinatorClient(); } public void setDbClient(DbClient dbClient) { this.dbClient = dbClient; this.shareDbClient(); } @PostConstruct public void init() throws Exception { } /** * Gets the target object for * * @param id * @return */ protected DiscoveredSystemObject getTarget(String id) throws ComputeSystemControllerException { try { DiscoveredSystemObject target = modelClient.findById(URI.create(id)); return target; } catch (Exception e) { LOG.error("Could not get discovery target: " + id); throw ComputeSystemControllerException.exceptions.targetNotFound(id); } } /** * Performs discovery of a given target. An exclusive lock is obtained for the target so that only a single node can * be performing discovery for any given object at a time. * * @param targetId * the ID of the target to discover. * * @throws Exception * if an error occurs obtaining a lock. */ public void discover(String targetId) throws Exception { InterProcessLock lock = coordinatorClient.getLock(targetId); if (LOG.isInfoEnabled()) { LOG.info("Acquiring lock for compute system discovery: {}", targetId); } lock.acquire(); try { if (LOG.isInfoEnabled()) { LOG.info("Acquired lock for compute system discovery: {}", targetId); } discoverInLock(targetId); } finally { lock.release(); if (LOG.isInfoEnabled()) { LOG.info("Lock Released for compute system discovery: {}", targetId); } } } /** * Performs the discovery, within a lock. * * @param targetId * the ID of the target to discover. */ protected void discoverInLock(String targetId) { DiscoveredSystemObject target = modelClient.findById(URI.create(targetId)); if (target == null) { LOG.error("Could not find: " + targetId); throw ComputeSystemControllerException.exceptions.targetNotFound(targetId); } ComputeSystemDiscoveryAdapter adapter = getDiscoveryAdapter(targetId); if (adapter != null) { if (LOG.isInfoEnabled()) { LOG.info("Discovering target " + target.getLabel() + " [" + targetId + "]"); } try { adapter.discoverTarget(targetId); if (LOG.isInfoEnabled()) { LOG.info("Discovery completed for " + target.getLabel() + " [" + targetId + "]"); } } catch (CompatibilityException e) { String errorMessage = adapter.getErrorMessage(e); LOG.error("Device is incompatible: " + target.getLabel() + " [" + targetId + "]: " + errorMessage); adapter.discoveryFailure(target, DiscoveredDataObject.CompatibilityStatus.INCOMPATIBLE.name(), errorMessage); throw e; } catch (RuntimeException e) { String errorMessage = adapter.getErrorMessage(e); LOG.error("Discovery failed for " + target.getLabel() + " [" + targetId + "]: " + errorMessage, e); adapter.discoveryFailure(target, DiscoveredDataObject.CompatibilityStatus.UNKNOWN.name(), errorMessage); throw ComputeSystemControllerException.exceptions.discoverFailed(targetId, e); } } else { LOG.warn("No discovery adapter for target " + target.getLabel() + " [" + targetId + "]"); target.setCompatibilityStatus(DiscoveredDataObject.CompatibilityStatus.UNKNOWN.name()); dbClient.persistObject(target); throw ComputeSystemControllerException.exceptions.discoveryAdapterNotFound(target.getLabel(), targetId); } } /** * Gets the discovery adapter to use for the given target. * * @param targetId * the ID of the target to discover. * @return the discovery adapter, or null if the target cannot be discovered. */ protected ComputeSystemDiscoveryAdapter getDiscoveryAdapter(String targetId) { for (ComputeSystemDiscoveryAdapter adapter : discoveryAdapters) { if (adapter.isSupportedTarget(targetId)) { return adapter; } } return null; } private void shareDbClient() { this.modelClient = new ModelClientImpl(dbClient); for (ComputeSystemDiscoveryAdapter discoveryAdapter : discoveryAdapters) { discoveryAdapter.setModelClient(this.modelClient); discoveryAdapter.setDbClient(this.dbClient); } } private void shareCoordinatorClient() { for (ComputeSystemDiscoveryAdapter discoveryAdapter : discoveryAdapters) { discoveryAdapter.getVersionValidator().setCoordinatorClient(this.coordinatorClient); discoveryAdapter.setCoordinator(this.coordinatorClient); } } }