/* * Copyright (c) 2016 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.plugins; import static com.emc.storageos.db.client.util.CustomQueryUtility.queryActiveResourcesByAltId; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.URIUtil; import com.emc.storageos.db.client.constraint.AlternateIdConstraint; import com.emc.storageos.db.client.constraint.ContainmentConstraint; import com.emc.storageos.db.client.constraint.URIQueryResultList; import com.emc.storageos.db.client.model.AutoTieringPolicy; import com.emc.storageos.db.client.model.DataObject; import com.emc.storageos.db.client.model.DiscoveredDataObject; import com.emc.storageos.db.client.model.Network; import com.emc.storageos.db.client.model.StorageHADomain; import com.emc.storageos.db.client.model.StorageSystemType; import com.emc.storageos.db.client.model.StringMap; import com.emc.storageos.db.client.model.StringSet; import com.emc.storageos.db.client.util.CustomQueryUtility; import com.emc.storageos.plugins.AccessProfile; import com.emc.storageos.plugins.BaseCollectionException; import com.emc.storageos.plugins.StorageSystemViewObject; import com.emc.storageos.storagedriver.AbstractStorageDriver; import com.emc.storageos.storagedriver.BlockStorageDriver; import com.emc.storageos.storagedriver.DiscoveryDriver; import com.emc.storageos.storagedriver.DriverTask; import com.emc.storageos.storagedriver.LockManager; import com.emc.storageos.storagedriver.Registry; import com.emc.storageos.storagedriver.StorageDriver; import com.emc.storageos.storagedriver.impl.LockManagerImpl; import com.emc.storageos.storagedriver.impl.RegistryImpl; import com.emc.storageos.storagedriver.model.StoragePool; import com.emc.storageos.storagedriver.model.StoragePort; import com.emc.storageos.storagedriver.model.StorageProvider; import com.emc.storageos.storagedriver.model.StorageSystem; import com.emc.storageos.storagedriver.storagecapabilities.AutoTieringPolicyCapabilityDefinition; import com.emc.storageos.storagedriver.storagecapabilities.CapabilityDefinition; import com.emc.storageos.storagedriver.storagecapabilities.CapabilityInstance; import com.emc.storageos.storagedriver.storagecapabilities.DeduplicationCapabilityDefinition; import com.emc.storageos.svcs.errorhandling.resources.ServiceCode; import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator; import com.emc.storageos.volumecontroller.impl.StoragePortAssociationHelper; import com.emc.storageos.volumecontroller.impl.externaldevice.ExternalDeviceCollectionException; import com.emc.storageos.volumecontroller.impl.externaldevice.ExternalDeviceUnManagedVolumeDiscoverer; import com.emc.storageos.volumecontroller.impl.plugins.metering.smis.processor.MetricsKeys; import com.emc.storageos.volumecontroller.impl.utils.DiscoveryUtils; /** * ExtendedCommunicationInterface implementation for SB SDK managed devices. */ public class ExternalDeviceCommunicationInterface extends ExtendedCommunicationInterfaceImpl { private static final String NEW = "new"; private static final String EXISTING = "existing"; private Logger _log = LoggerFactory.getLogger(ExternalDeviceCommunicationInterface.class); private Map<String, AbstractStorageDriver> drivers; // Indicate if driver info has been fetched from db and merged into drivers member private boolean initialized = false; // The common capability definitions supported by the SB SDK. private Map<String, CapabilityDefinition> capabilityDefinitions; private ExternalDeviceUnManagedVolumeDiscoverer unManagedVolumeDiscoverer; private ExternalDeviceUnManagedVolumeDiscoverer unManagedFileSystemDiscoverer; // Initialized drivers map private Map<String, AbstractStorageDriver> discoveryDrivers = new HashMap<>(); public void setUnManagedVolumeDiscoverer(ExternalDeviceUnManagedVolumeDiscoverer unManagedVolumeDiscoverer) { this.unManagedVolumeDiscoverer = unManagedVolumeDiscoverer; } public void setDrivers(Map<String, AbstractStorageDriver> drivers) { this.drivers = drivers; } /** * Setter for the common capability definitions supported by the SB SDK. * * @param capabilityDefinitions The map common of capability definitions keyed by their unique id. */ public void setCapabilityDefinitions(Map<String, CapabilityDefinition> capabilityDefinitions) { this.capabilityDefinitions = capabilityDefinitions; } private void initDrivers() { if (initialized) { return; } List<URI> ids = _dbClient.queryByType(StorageSystemType.class, true); Iterator<StorageSystemType> it = _dbClient.queryIterativeObjects(StorageSystemType.class, ids); Map<String, AbstractStorageDriver> cachedDriverInstances = new HashMap<>(); while (it.hasNext()) { StorageSystemType type = it.next(); if (type.getIsNative() == null ||type.getIsNative()) { continue; } if (!StringUtils.equals(type.getMetaType(), StorageSystemType.META_TYPE.BLOCK.toString())) { continue; } String typeName = type.getStorageTypeName(); String className = type.getDriverClassName(); // provider and managed system should use the same driver instance if (cachedDriverInstances.containsKey(className)) { drivers.put(typeName, cachedDriverInstances.get(className)); _log.info("Driver info for storage system type {} has been set into externaldevice instance", typeName); continue; } String mainClassName = type.getDriverClassName(); try { AbstractStorageDriver driverInstance = (AbstractStorageDriver) Class.forName(mainClassName) .newInstance(); drivers.put(typeName, driverInstance); cachedDriverInstances.put(className, driverInstance); _log.info("Driver info for storage system type {} has been set into externaldevice instance", typeName); } catch (Exception e) { _log.error("Error happened when instantiating class {}", mainClassName); } } initialized = true; } /** * Get device driver based on the driver type. * @param driverType * @return driver */ private synchronized AbstractStorageDriver getDriver(String driverType) { // look up driver AbstractStorageDriver discoveryDriver = discoveryDrivers.get(driverType); if (discoveryDriver != null) { return discoveryDriver; } else { // init driver AbstractStorageDriver driver = drivers.get(driverType); if (driver == null) { initDrivers(); driver = drivers.get(driverType); if (driver == null) { _log.info("No driver entry defined for device type: {} . ", driverType); return null; } } init(driver); discoveryDrivers.put(driverType, driver); return driver; } } /** * Init device driver. Sets registry and lock manager to the driver. * @param driver */ private void init(AbstractStorageDriver driver) { Registry driverRegistry = RegistryImpl.getInstance(_dbClient); driver.setDriverRegistry(driverRegistry); LockManager lockManager = LockManagerImpl.getInstance(_locker); driver.setLockManager(lockManager); driver.setSdkVersionNumber(StorageDriver.SDK_VERSION_NUMBER); } @Override public void collectStatisticsInformation(AccessProfile accessProfile) throws BaseCollectionException { // todo _log.info("Entering {}", Thread.currentThread().getStackTrace()[1].getMethodName()); _log.info("Collect statistic information for external device of type {} is not supported", accessProfile.getSystemType()); _log.info("Exiting {}", Thread.currentThread().getStackTrace()[1].getMethodName()); } @Override public void scan(AccessProfile accessProfile) throws BaseCollectionException { // Initialize driver instance for storage provider, // call driver to scan the provider to get list of managed storage systems, // update the system with this information. _log.info("Scanning started for provider: {}", accessProfile.getSystemId()); com.emc.storageos.db.client.model.StorageProvider.ConnectionStatus cxnStatus = com.emc.storageos.db.client.model.StorageProvider.ConnectionStatus.CONNECTED; // Get discovery driver class based on storage device type String deviceType = accessProfile.getSystemType(); AbstractStorageDriver driver = getDriver(deviceType); if (driver == null) { String errorMsg = String.format("No driver entry defined for device type: %s . ", deviceType); _log.info(errorMsg); throw new ExternalDeviceCollectionException(false, ServiceCode.DISCOVERY_ERROR, null, errorMsg, null, null); } com.emc.storageos.db.client.model.StorageProvider storageProvider = null; try { storageProvider = _dbClient.queryObject(com.emc.storageos.db.client.model.StorageProvider.class, accessProfile.getSystemId()); String username = storageProvider.getUserName(); String password = storageProvider.getPassword(); String hostName = storageProvider.getIPAddress(); Integer portNumber = storageProvider.getPortNumber(); String providerType = storageProvider.getInterfaceType(); Boolean useSsl = storageProvider.getUseSSL(); String msg = String.format("Storage provider info: type: %s, host: %s, port: %s, user: %s, useSsl: %s", providerType, hostName, portNumber, username, useSsl); _log.info(msg); StorageProvider driverProvider = new StorageProvider(); // initialize driver provider driverProvider.setProviderHost(hostName); driverProvider.setPortNumber(portNumber); driverProvider.setUsername(username); driverProvider.setPassword(password); driverProvider.setUseSSL(useSsl); // call the driver List<StorageSystem> systems = new ArrayList<>(); DriverTask task = driver.discoverStorageProvider(driverProvider, systems); // todo: need to implement support for async case. if (task.getStatus() == DriverTask.TaskStatus.READY) { // process results, populate cache _log.info("Scan: found {} systems for provider {}", systems.size(), accessProfile.getSystemId()); //update provider with scan info storageProvider.setVersionString(driverProvider.getProviderVersion()); if (driverProvider.isSupportedVersion()) { storageProvider.setCompatibilityStatus(DiscoveredDataObject.CompatibilityStatus.COMPATIBLE.name()); } else { storageProvider.setCompatibilityStatus(DiscoveredDataObject.CompatibilityStatus.INCOMPATIBLE.name()); String errorMsg = String.format("Storage provider %s has version %s which is not supported by driver", storageProvider.getIPAddress(), storageProvider.getVersionString()); throw new ExternalDeviceCollectionException(false, ServiceCode.DISCOVERY_ERROR, null, errorMsg, null, null); } // process storage system cache Map<String, StorageSystemViewObject> storageSystemsCache = accessProfile.getCache(); for (StorageSystem driverStorageSystem : systems) { String systemType = driverStorageSystem.getSystemType(); String nativeGuid = NativeGUIDGenerator.generateNativeGuid(systemType, driverStorageSystem.getNativeId()); StorageSystemViewObject storageSystemView = storageSystemsCache.get(nativeGuid); if (storageSystemView == null) { storageSystemView = new StorageSystemViewObject(); } storageSystemView.setDeviceType(systemType); storageSystemView.addprovider(accessProfile.getSystemId().toString()); storageSystemView.setProperty(StorageSystemViewObject.SERIAL_NUMBER, driverStorageSystem.getSerialNumber()); storageSystemView.setProperty(StorageSystemViewObject.VERSION, driverStorageSystem.getFirmwareVersion()); storageSystemView.setProperty(StorageSystemViewObject.STORAGE_NAME, driverStorageSystem.getNativeId()); storageSystemsCache.put(nativeGuid, storageSystemView); _log.info(String.format("Info for storage system %s (provider ip %s): type: %s, nativeGuid: %s", driverStorageSystem.getSerialNumber(), accessProfile.getIpAddress(), systemType, nativeGuid)); } } else { // task status is not ready String errorMsg = String.format("Failed to scan provider %s of type %s. \n" + " Driver task message: %s", accessProfile.getSystemId(), accessProfile.getSystemType(), task.getMessage()); throw new ExternalDeviceCollectionException(false, ServiceCode.DISCOVERY_ERROR, null, errorMsg, null, null); } } catch (Exception ex) { _log.error("Error scanning provider: {} of type: {} .", accessProfile.getIpAddress(), accessProfile.getSystemType(), ex); cxnStatus = com.emc.storageos.db.client.model.StorageProvider.ConnectionStatus.NOTCONNECTED; throw ex; } finally { if (storageProvider != null) { storageProvider.setConnectionStatus(cxnStatus.name()); _dbClient.updateObject(storageProvider); } _log.info("Completed scan of {} provider: ", accessProfile.getSystemType(), accessProfile.getIpAddress()); } } @Override public void discover(AccessProfile accessProfile) throws BaseCollectionException { // Get discovery driver class based on storage device type String deviceType = accessProfile.getSystemType(); AbstractStorageDriver driver = getDriver(deviceType); if (driver == null) { String errorMsg = String.format("No driver entry defined for device type: %s . ", deviceType); _log.info(errorMsg); throw new ExternalDeviceCollectionException(false, ServiceCode.DISCOVERY_ERROR, null, errorMsg, null, null); } try { if (null != accessProfile.getnamespace() && (accessProfile.getnamespace().equals(com.emc.storageos.db.client.model.StorageSystem.Discovery_Namespaces.UNMANAGED_VOLUMES.toString()))) { discoverUnManagedBlockObjects(driver, accessProfile); _completer.statusReady(_dbClient, "Completed unmanaged block object discovery"); } else if (null != accessProfile.getnamespace() && (accessProfile.getnamespace().equals(com.emc.storageos.db.client.model.StorageSystem.Discovery_Namespaces.UNMANAGED_FILESYSTEMS.toString()))){ _log.warn("Discovery of unmanaged file systems is not supported for external storage system of type {}", accessProfile.getSystemType()); } else { // discover storage system discoverStorageSystem(driver, accessProfile); _completer.statusPending(_dbClient, "Completed storage system discovery"); // discover storage pools List<com.emc.storageos.db.client.model.StoragePool> storagePools = discoverStoragePools(driver, accessProfile); List<com.emc.storageos.db.client.model.StoragePool> storagePoolsToMatchWithVpools = new ArrayList<>(); storagePoolsToMatchWithVpools.addAll(storagePools); List<com.emc.storageos.db.client.model.StoragePool> notVisiblePools = DiscoveryUtils.checkStoragePoolsNotVisible(storagePools, _dbClient, accessProfile.getSystemId()); storagePoolsToMatchWithVpools.addAll(notVisiblePools); _completer.statusPending(_dbClient, "Completed storage pools discovery"); // discover ports List<com.emc.storageos.db.client.model.StoragePort> allPorts = new ArrayList<>(); Set<Network> networksToUpdate = new HashSet<>(); Map<String, List<com.emc.storageos.db.client.model.StoragePort>> ports = discoverStoragePorts(driver, networksToUpdate, accessProfile); _log.info("No of newly discovered ports {}", ports.get(NEW).size()); _log.info("No of existing discovered ports {}", ports.get(EXISTING).size()); if (null != ports && !ports.get(NEW).isEmpty()) { allPorts.addAll(ports.get(NEW)); _dbClient.createObject(ports.get(NEW)); } if (null != ports && !ports.get(EXISTING).isEmpty()) { allPorts.addAll(ports.get(EXISTING)); _dbClient.updateObject(ports.get(EXISTING)); } if (!networksToUpdate.isEmpty()) { _dbClient.updateObject(networksToUpdate); } List<com.emc.storageos.db.client.model.StoragePort> notVisiblePorts = DiscoveryUtils.checkStoragePortsNotVisible(allPorts, _dbClient, accessProfile.getSystemId()); List<com.emc.storageos.db.client.model.StoragePort> allExistPorts = new ArrayList<>(ports.get(EXISTING)); allExistPorts.addAll(notVisiblePorts); _completer.statusPending(_dbClient, "Completed port discovery"); StoragePortAssociationHelper.runUpdatePortAssociationsProcess(ports.get(NEW), allExistPorts, _dbClient, _coordinator, storagePoolsToMatchWithVpools); _completer.statusReady(_dbClient, "Completed storage discovery"); } } catch (BaseCollectionException bEx) { _completer.error(_dbClient, bEx); throw bEx; } } public void discoverUnManagedBlockObjects(AbstractStorageDriver driver, AccessProfile accessProfile) { String detailedStatusMessage; com.emc.storageos.db.client.model.StorageSystem storageSystem = _dbClient.queryObject(com.emc.storageos.db.client.model.StorageSystem.class, accessProfile.getSystemId()); if (null == storageSystem) { return; } try { _log.info("discoverUnManagedBlockObjects information for storage system {}, native id {} - start", accessProfile.getSystemId(), storageSystem.getNativeGuid()); storageSystem.setDiscoveryStatus(DiscoveredDataObject.DataCollectionJobStatus.IN_PROGRESS.toString()); _dbClient.updateObject(storageSystem); if (accessProfile.getnamespace().equals(com.emc.storageos.db.client.model.StorageSystem.Discovery_Namespaces.UNMANAGED_VOLUMES.toString())) { unManagedVolumeDiscoverer.discoverUnManagedBlockObjects((BlockStorageDriver) driver, storageSystem, _dbClient, _partitionManager); } // discovery succeeds detailedStatusMessage = String.format("discoverUnManagedBlockObjects completed successfully for %s: %s", storageSystem.getNativeId(), storageSystem.getId().toString()); _log.info(detailedStatusMessage); } catch (Exception e) { String message = String.format("discoverUnManagedBlockObjects failed for system %s with native id %s : %s .", storageSystem.getId(), storageSystem.getNativeGuid(), e.getMessage()); _log.error(message, e); storageSystem.setLastDiscoveryStatusMessage(message); throw e; } finally { _dbClient.updateObject(storageSystem); _log.info("discoverUnManagedBlockObjects for system {} of type {} - end", accessProfile.getSystemId(), accessProfile.getSystemType()); } } private void discoverStorageSystem(DiscoveryDriver driver, AccessProfile accessProfile) throws BaseCollectionException { StorageSystem driverStorageSystem = new StorageSystem(); driverStorageSystem.setIpAddress(accessProfile.getIpAddress()); driverStorageSystem.setPortNumber(accessProfile.getPortNumber()); driverStorageSystem.setUsername(accessProfile.getUserName()); driverStorageSystem.setPassword(accessProfile.getPassword()); com.emc.storageos.db.client.model.StorageSystem storageSystem = _dbClient.queryObject(com.emc.storageos.db.client.model.StorageSystem.class, accessProfile.getSystemId()); driverStorageSystem.setSystemName(storageSystem.getLabel()); driverStorageSystem.setDisplayName(storageSystem.getLabel()); // could be already populated by scan if (storageSystem.getSerialNumber() != null) { driverStorageSystem.setSerialNumber(storageSystem.getSerialNumber()); _log.info("discoverStorageSystem: set serial number to {}", driverStorageSystem.getSerialNumber()); } // could be already populated by scan if (storageSystem.getNativeId() != null) { driverStorageSystem.setNativeId(storageSystem.getNativeId()); _log.info("discoverStorageSystem: set nativeId to {}", driverStorageSystem.getNativeId()); } try { _log.info("discoverStorageSystem information for storage system {}, name {}, ip address (), port {} - start", accessProfile.getSystemId(), driverStorageSystem.getSystemName(), driverStorageSystem.getIpAddress(), driverStorageSystem.getPortNumber()); DriverTask task = driver.discoverStorageSystem(driverStorageSystem); // process discovery results. // todo: need to implement support for async case. if (task.getStatus() == DriverTask.TaskStatus.READY) { // discovery completed storageSystem.setIsDriverManaged(true); storageSystem.setSerialNumber(driverStorageSystem.getSerialNumber()); storageSystem.setNativeId(driverStorageSystem.getNativeId()); String nativeGuid = NativeGUIDGenerator.generateNativeGuid(accessProfile.getSystemType(), driverStorageSystem.getNativeId()); storageSystem.setNativeGuid(nativeGuid); storageSystem.setFirmwareVersion(driverStorageSystem.getFirmwareVersion()); if (driverStorageSystem.getSupportedReplications() != null) { _log.info("Set async actions..."); StringSet asyncActions = new StringSet(); Set<StorageSystem.SupportedReplication> replications = driverStorageSystem.getSupportedReplications(); for (StorageSystem.SupportedReplication replication : replications) { if (replication == StorageSystem.SupportedReplication.elementReplica) { asyncActions.add(com.emc.storageos.db.client.model.StorageSystem.AsyncActions.CreateElementReplica.name()); } else if (replication == StorageSystem.SupportedReplication.groupReplica){ asyncActions.add(com.emc.storageos.db.client.model.StorageSystem.AsyncActions.CreateGroupReplica.name()); } } storageSystem.setSupportedAsynchronousActions(asyncActions); } if (driverStorageSystem.isSupportedVersion()) { storageSystem.setCompatibilityStatus(DiscoveredDataObject.CompatibilityStatus.COMPATIBLE.name()); storageSystem.setReachableStatus(true); } else { storageSystem.setCompatibilityStatus(DiscoveredDataObject.CompatibilityStatus.INCOMPATIBLE.name()); storageSystem.setReachableStatus(false); DiscoveryUtils.setSystemResourcesIncompatible(_dbClient, _coordinator, storageSystem.getId()); String errorMsg = String.format("Storage array %s has firmware version %s which is not supported by driver", storageSystem.getNativeGuid(), storageSystem.getFirmwareVersion()); throw new ExternalDeviceCollectionException(false, ServiceCode.DISCOVERY_ERROR, null, errorMsg, null, null); } } else { storageSystem.setReachableStatus(false); String errorMsg = String.format("Failed to discover storage system %s of type %s. \n" + " Driver task message: %s ", accessProfile.getSystemId(), accessProfile.getSystemType(), task.getMessage()); throw new ExternalDeviceCollectionException(false, ServiceCode.DISCOVERY_ERROR, null, errorMsg, null, null); } String message = String.format("Storage array %s with native id %s was discovered successfully.", storageSystem.getId(), storageSystem.getNativeGuid()); _log.info(message); storageSystem.setLastDiscoveryStatusMessage(message); } catch (Exception e) { if (storageSystem != null) { String message = String.format("Failed to discover storage array %s with native id %s : %s .", storageSystem.getId(), storageSystem.getNativeGuid(), e.getMessage()); storageSystem.setLastDiscoveryStatusMessage(message); _log.error(message, e); } throw e; } finally { if (storageSystem != null) { _dbClient.updateObject(storageSystem); } _log.info("Discovery of storage system {} of type {} - end", accessProfile.getSystemId(), accessProfile.getSystemType()); } } private List<com.emc.storageos.db.client.model.StoragePool> discoverStoragePools(DiscoveryDriver driver, AccessProfile accessProfile) throws BaseCollectionException { // Discover storage pools and associated auto tiering policies. List<StoragePool> driverStoragePools = new ArrayList<>(); List<com.emc.storageos.db.client.model.StoragePool> allPools = new ArrayList<>(); List<com.emc.storageos.db.client.model.StoragePool> newPools = new ArrayList<>(); List<com.emc.storageos.db.client.model.StoragePool> existingPools = new ArrayList<>(); Map<String, List<com.emc.storageos.db.client.model.StoragePool>> autoTieringPolicyPoolMap = new HashMap<>(); Map<String, Map<String, List<String>>> autoTieringPolicyPropertiesMap = new HashMap<>(); com.emc.storageos.db.client.model.StorageSystem storageSystem = _dbClient.queryObject(com.emc.storageos.db.client.model.StorageSystem.class, accessProfile.getSystemId()); URI storageSystemId = storageSystem.getId(); StorageSystem driverStorageSystem = initStorageSystem(storageSystem); try { _log.info("discoverPools for storage system {} - start", storageSystemId); DriverTask task = driver.discoverStoragePools(driverStorageSystem, driverStoragePools); // todo: need to implement support for async case. if (task.getStatus() == DriverTask.TaskStatus.READY) { // discovery completed for (StoragePool storagePool : driverStoragePools) { com.emc.storageos.db.client.model.StoragePool pool; // Check if this storage pool was already discovered String poolNativeGuid = NativeGUIDGenerator.generateNativeGuid( storageSystem, storagePool.getNativeId(), NativeGUIDGenerator.POOL); List<com.emc.storageos.db.client.model.StoragePool> pools = queryActiveResourcesByAltId(_dbClient, com.emc.storageos.db.client.model.StoragePool.class, "nativeGuid", poolNativeGuid); if (pools.isEmpty()) { _log.info("Pool {} is new, native GUID {}", storagePool.getNativeId(), poolNativeGuid); pool = new com.emc.storageos.db.client.model.StoragePool(); pool.setId(URIUtil.createId(com.emc.storageos.db.client.model.StoragePool.class)); pool.setIsDriverManaged(true); pool.setStorageDevice(accessProfile.getSystemId()); pool.setNativeId(storagePool.getNativeId()); pool.setNativeGuid(poolNativeGuid); pool.setPoolName(storagePool.getPoolName()); pool.addProtocols(storagePool.getProtocols()); pool.setPoolServiceType(storagePool.getPoolServiceType()); pool.setCompatibilityStatus(storageSystem.getCompatibilityStatus()); if (storagePool.getMaximumThickVolumeSize() != null) { pool.setMaximumThickVolumeSize(storagePool.getMaximumThickVolumeSize()); } else { pool.setMaximumThickVolumeSize(Long.MAX_VALUE); } if (storagePool.getMinimumThickVolumeSize() != null) { pool.setMinimumThickVolumeSize(storagePool.getMinimumThickVolumeSize()); } else { pool.setMinimumThickVolumeSize(0L); } if (storagePool.getMaximumThinVolumeSize() != null) { pool.setMaximumThinVolumeSize(storagePool.getMaximumThinVolumeSize()); } else { pool.setMaximumThinVolumeSize(Long.MAX_VALUE); } if (storagePool.getMinimumThinVolumeSize() != null) { pool.setMinimumThinVolumeSize(storagePool.getMinimumThinVolumeSize()); } else { pool.setMinimumThinVolumeSize(0L); } pool.setSupportedResourceTypes(storagePool.getSupportedResourceType()); pool.setInactive(false); newPools.add(pool); } else if (pools.size() == 1) { _log.info("Pool {} was previously discovered, native GUID {}", storagePool.getNativeId(), poolNativeGuid); pool = pools.get(0); existingPools.add(pool); } else { _log.warn(String.format("There are %d StoragePools with nativeGuid = %s", pools.size(), poolNativeGuid)); continue; } // applicable to new and existing storage pools pool.setSubscribedCapacity(storagePool.getSubscribedCapacity()); pool.setFreeCapacity(storagePool.getFreeCapacity()); pool.setTotalCapacity(storagePool.getTotalCapacity()); pool.setOperationalStatus(storagePool.getOperationalStatus()); pool.addDriveTypes(storagePool.getSupportedDriveTypes()); pool.addSupportedRaidLevels(storagePool.getSupportedRaidLevels()); pool.setDiscoveryStatus(DiscoveredDataObject.DiscoveryStatus.VISIBLE.name()); // Discover the auto tiering policies supported by the storage pool. discoverAutoTieringPoliciesForStoragePool(driverStorageSystem, storagePool, pool, autoTieringPolicyPoolMap, autoTieringPolicyPropertiesMap); // Discover deduplication capability for storage pool. discoverDeduplicationCapabilityForStoragePool(driverStorageSystem, storagePool, pool); } // Now that all storage pools have been process we can create or update // as necessary the auto tiering policy instances in the controller. createOrUpdateAutoTierPolicies(storageSystem, autoTieringPolicyPoolMap, autoTieringPolicyPropertiesMap); _log.info("No of newly discovered pools {}", newPools.size()); _log.info("No of existing discovered pools {}", existingPools.size()); _dbClient.createObject(newPools); _dbClient.updateObject(existingPools); allPools.addAll(newPools); allPools.addAll(existingPools); } else { String errorMsg = String.format("Failed to discover storage pools for system %s of type %s . \n" + " Driver task message: %s", accessProfile.getSystemId(), accessProfile.getSystemType(), task.getMessage()); storageSystem.setLastDiscoveryStatusMessage(errorMsg); throw new ExternalDeviceCollectionException(false, ServiceCode.DISCOVERY_ERROR, null, errorMsg, null, null); } String message = String.format("Storage pools of storage array %s with native id %s were discovered successfully.", storageSystem.getId(), storageSystem.getNativeGuid()); _log.info(message); return allPools; } catch (Exception e) { String message = String.format("Failed to discover storage pools of storage array %s with native id %s : %s .", storageSystem.getId(), storageSystem.getNativeGuid(), e.getMessage()); _log.error(message, e); storageSystem.setLastDiscoveryStatusMessage(message); throw e; } finally { _dbClient.updateObject(storageSystem); _log.info("Discovery of storage pools of storage system {} of type {} - end", accessProfile.getSystemId(), accessProfile.getSystemType()); } } /** * Discovers the auto tiering policies supported by the passed driver storage pool * and updates the passed auto tiering policy maps. * * @param driverStorageSystem A reference to the driver storage system. * @param storagePool A reference to the driver storage pool. * @param pool A reference to the controller storage pool representing the driver storage pool. * @param autoTieringPolicyPoolMap A map of unique policy ids and controller storage pools that support the policy. * @param autoTieringPolicyPropertiesMap A map of unique policy ids and the policy properties. */ private void discoverAutoTieringPoliciesForStoragePool(StorageSystem driverStorageSystem, StoragePool storagePool, com.emc.storageos.db.client.model.StoragePool pool, Map<String, List<com.emc.storageos.db.client.model.StoragePool>> autoTieringPolicyPoolMap, Map<String, Map<String, List<String>>> autoTieringPolicyPropertiesMap) { // Get the capabilities specified for the storage pool and // process any auto tiering policy capabilities. List<CapabilityInstance> capabilities = storagePool.getCapabilities(); if (capabilities == null) { return; } for (CapabilityInstance capability : capabilities) { // Get the capability definition for the capability. String capabilityDefinitionUid = capability.getCapabilityDefinitionUid(); if ((capabilityDefinitionUid == null) || (capabilityDefinitionUid.isEmpty())) { _log.error(String.format("Skipping capability %s with no capability definition UID for storage pool %s on system %s", capability.getName(), storagePool.getNativeId(), driverStorageSystem.getNativeId())); continue; } // Get the capability definition from the map of supported capability definitions. CapabilityDefinition capabilityDefinition = capabilityDefinitions.get(capabilityDefinitionUid); if (capabilityDefinition == null) { _log.info(String.format("Skipping unsupported capability of type %s for storage pool %s on system %s", capabilityDefinitionUid, storagePool.getNativeId(), driverStorageSystem.getNativeId())); continue; } // Handle auto tiering policy capability. if (AutoTieringPolicyCapabilityDefinition.CAPABILITY_UID.equals(capabilityDefinitionUid)) { // Get the policy id. String policyId = capability.getPropertyValue(AutoTieringPolicyCapabilityDefinition.PROPERTY_NAME.POLICY_ID.name()); if (policyId == null) { _log.error(String.format("Skipping auto tiering policy capability %s with no policy id for storage pool %s on system %s", capability.getName(), storagePool.getNativeId(), driverStorageSystem.getNativeId())); continue; } // Add the pool to the set of storage pools for this auto tiering policy. if (autoTieringPolicyPoolMap.containsKey(policyId)) { List<com.emc.storageos.db.client.model.StoragePool> autoTieringPolicyPools = autoTieringPolicyPoolMap.get(policyId); autoTieringPolicyPools.add(pool); } else { List<com.emc.storageos.db.client.model.StoragePool> autoTieringPolicyPools = new ArrayList<>(); autoTieringPolicyPools.add(pool); autoTieringPolicyPoolMap.put(policyId, autoTieringPolicyPools); } // Also, save the properties for this auto tiering policy. if (!autoTieringPolicyPropertiesMap.containsKey(policyId)) { autoTieringPolicyPropertiesMap.put(policyId, capability.getProperties()); } } } } /** * Discover deduplication capability for storage pool. * If driver does not report "deduplication" for storage pool, we assume that deduplication is disabled. * If driver reports "deduplication" for storage pool, we assume that it is enabled, unless its ENABLED property is set to false. * * @param driverStorageSystem A reference to the driver storage system. * @param driverPool A reference to the driver storage pool. * @param dbPool A reference to the system storage pool representing the driver storage pool. */ private void discoverDeduplicationCapabilityForStoragePool(StorageSystem driverStorageSystem, StoragePool driverPool, com.emc.storageos.db.client.model.StoragePool dbPool) { // Get the capabilities specified for the storage pool and // process and process deduplication capability if reported by driver List<CapabilityInstance> capabilities = driverPool.getCapabilities(); if (capabilities == null) { return; } for (CapabilityInstance capability : capabilities) { // Get the capability definition for the capability. String capabilityDefinitionUid = capability.getCapabilityDefinitionUid(); if ((capabilityDefinitionUid == null) || (capabilityDefinitionUid.isEmpty())) { _log.error(String.format( "Skipping capability %s with no capability definition UID for storage pool %s on system %s", capability.getName(), driverPool.getNativeId(), driverStorageSystem.getNativeId())); continue; } // Get the capability definition from the map of supported // capability definitions. CapabilityDefinition capabilityDefinition = capabilityDefinitions.get(capabilityDefinitionUid); if (capabilityDefinition == null) { _log.info(String.format("Skipping unsupported capability of type %s for storage pool %s on system %s", capabilityDefinitionUid, driverPool.getNativeId(), driverStorageSystem.getNativeId())); continue; } if (DeduplicationCapabilityDefinition.CAPABILITY_UID.equals(capabilityDefinitionUid)) { // Handle dedup capability. // Check if dedup is enabled; we assume that if driver reports deduplication in pool capabilities, // it is enabled by default, unless it is explicitly disabled. String isEnabled = capability.getPropertyValue(DeduplicationCapabilityDefinition.PROPERTY_NAME.ENABLED.name()); if (isEnabled != null && isEnabled.equalsIgnoreCase("false") ) { _log.info(String.format("StoragePool %s of storage system %s has deduplication disabled", driverPool.getNativeId(), driverStorageSystem.getNativeId())); dbPool.setDedupCapable(false); } else { _log.info(String.format("Enable deduplication for StoragePool %s of storage system %s ", driverPool.getNativeId(), driverStorageSystem.getNativeId())); dbPool.setDedupCapable(true); } } } } /** * Creates and/or updates the auto tiering policies in the controller database after * processing the discovered storage pools and the auto tiering policies that they support. * * @param system A reference to the storage system. * @param autoTieringPolicyPoolMap A map of the storage pools for each policy keyed by policy id. * @param autoTieringPolicyPropertiesMap A map of the auto tiering policy properties keyed by policy id. */ private void createOrUpdateAutoTierPolicies(com.emc.storageos.db.client.model.StorageSystem system, Map<String, List<com.emc.storageos.db.client.model.StoragePool>> autoTieringPolicyPoolMap, Map<String, Map<String, List<String>>> autoTieringPolicyPropertiesMap) { List<DataObject> objectsToCreate = new ArrayList<>(); List<DataObject> objectsToUpdate = new ArrayList<>(); for (Entry<String, List<com.emc.storageos.db.client.model.StoragePool>> policyEntry : autoTieringPolicyPoolMap.entrySet()) { String policyId = policyEntry.getKey(); String nativeGuid = NativeGUIDGenerator.generateAutoTierPolicyNativeGuid(system.getNativeGuid(), policyId, NativeGUIDGenerator.AUTO_TIERING_POLICY); AutoTieringPolicy autoTieringPolicy = checkAutoTieringPolicyExistsInDB(nativeGuid); if (autoTieringPolicy == null) { autoTieringPolicy = new AutoTieringPolicy(); autoTieringPolicy.setId(URIUtil.createId(AutoTieringPolicy.class)); autoTieringPolicy.setPolicyName(policyId); autoTieringPolicy.setStorageSystem(system.getId()); autoTieringPolicy.setNativeGuid(nativeGuid); autoTieringPolicy.setLabel(policyId); autoTieringPolicy.setSystemType(system.getSystemType()); autoTieringPolicy.setPolicyEnabled(Boolean.TRUE); Map<String, List<String>> policyProperties = autoTieringPolicyPropertiesMap.get(policyId); List<String> provTypeValueList = policyProperties.get(AutoTieringPolicyCapabilityDefinition.PROPERTY_NAME.PROVISIONING_TYPE.name()); if (!provTypeValueList.isEmpty()) { autoTieringPolicy.setProvisioningType(provTypeValueList.get(0)); } objectsToCreate.add(autoTieringPolicy); _log.info(String.format("Creating new auto tiering policy %s, supported by storage pools %s", policyId, policyEntry.getValue())); } else { objectsToUpdate.add(autoTieringPolicy); _log.info(String.format("Updating existing auto tiering policy %s, supported by storage pools %s", policyId, policyEntry.getValue())); } // Set the storage pools for this policy. Since the pools have enabled auto // tiering policies, also, make sure auto tiering is enabled on each pool. StringSet poolIds = new StringSet(); for (com.emc.storageos.db.client.model.StoragePool pool : policyEntry.getValue()) { poolIds.add(pool.getId().toString()); // Note that the pool in the db will be updated by the caller. pool.setAutoTieringEnabled(true); } autoTieringPolicy.setPools(poolIds); // Lastly, since the system has pools with auto tiering enabled, make // sure the system has auto tiering enabled. if (!system.getAutoTieringEnabled()) { system.setAutoTieringEnabled(true); _dbClient.updateObject(system); } } // Now any auto tier policies in the database for the passed system that are // not represented by the passed policy map need to be marked disabled. disableRemovedAutoTieringPolicies(autoTieringPolicyPoolMap.keySet(), system.getId()); // Lastly create and update objects in the database. _dbClient.createObject(objectsToCreate); _dbClient.updateObject(objectsToUpdate); } /** * Get the auto tiering policy in the database with the passed native GUID if it exists. * Otherwise, return null. * * @param nativeGuid The native GUI of the auto tiering policy. * * @return The auto tiering policy if it exists, null otherwise. */ private AutoTieringPolicy checkAutoTieringPolicyExistsInDB(String nativeGuid) { AutoTieringPolicy autoTieringPolicy = null; URIQueryResultList queryResult = new URIQueryResultList(); _dbClient.queryByConstraint(AlternateIdConstraint.Factory.getAutoTieringPolicyByNativeGuidConstraint(nativeGuid), queryResult); if (queryResult.iterator().hasNext()) { autoTieringPolicy = _dbClient.queryObject(AutoTieringPolicy.class, queryResult.iterator().next()); } return autoTieringPolicy; } /** * Disable any auto tiering policies for the passed system that were not discovered * as represented by the passed policy ids. * * @param discoveredPolicyIds The ids of the discovered auto tiering policies * after processing all discovered storage pools. * @param systemURI The URI of the external storage system. */ private void disableRemovedAutoTieringPolicies(Set<String> discoveredPolicyIds, URI systemURI) { List<AutoTieringPolicy> disabledPolicies = new ArrayList<>(); URIQueryResultList queryResults = new URIQueryResultList(); _dbClient.queryByConstraint(ContainmentConstraint.Factory.getStorageDeviceFASTPolicyConstraint(systemURI), queryResults); Iterator<URI> queryResultsIter = queryResults.iterator(); while (queryResultsIter.hasNext()) { URI autoTieringPolicyURI = queryResultsIter.next(); AutoTieringPolicy autoTieringPolicy = _dbClient.queryObject(AutoTieringPolicy.class, autoTieringPolicyURI); if ((autoTieringPolicy != null) && (!discoveredPolicyIds.contains(autoTieringPolicy.getPolicyName()))) { // Disable the policy and clear the supporting storage pools. autoTieringPolicy.setPolicyEnabled(false); autoTieringPolicy.setPools(new StringSet()); autoTieringPolicy.setInactive(true); disabledPolicies.add(autoTieringPolicy); } } _dbClient.updateObject(disabledPolicies); } private Map<String, List<com.emc.storageos.db.client.model.StoragePort>> discoverStoragePorts(DiscoveryDriver driver, Set<Network> networksToUpdate, AccessProfile accessProfile) throws BaseCollectionException { URI storageSystemId = accessProfile.getSystemId(); com.emc.storageos.db.client.model.StorageSystem storageSystem = _dbClient.queryObject(com.emc.storageos.db.client.model.StorageSystem.class, storageSystemId); Map<String, List<com.emc.storageos.db.client.model.StoragePort>> storagePorts = new HashMap<>(); Map<StoragePort, com.emc.storageos.db.client.model.StoragePort> driverPortsToDBPorts = new HashMap<>(); List<com.emc.storageos.db.client.model.StoragePort> newStoragePorts = new ArrayList<>(); List<com.emc.storageos.db.client.model.StoragePort> existingStoragePorts = new ArrayList<>(); List<String> endpoints = new ArrayList<>(); StorageSystem driverStorageSystem = initStorageSystem(storageSystem); // Discover storage ports try { _log.info("discoverPorts for storage system {} - start", storageSystemId); List<StoragePort> driverStoragePorts = new ArrayList<>(); // Call driver. DriverTask task = driver.discoverStoragePorts(driverStorageSystem, driverStoragePorts); // todo: need to implement support for async case. if (task.getStatus() == DriverTask.TaskStatus.READY) { for (StoragePort driverPort : driverStoragePorts) { com.emc.storageos.db.client.model.StoragePort storagePort = null; String portNativeGuid = NativeGUIDGenerator.generateNativeGuid( storageSystem, driverPort.getNativeId(), NativeGUIDGenerator.PORT); // Check if storage port was already discovered @SuppressWarnings("deprecation") List<URI> portURIs = _dbClient.queryByConstraint(AlternateIdConstraint.Factory. getStoragePortByNativeGuidConstraint(portNativeGuid)); for (URI portUri : portURIs) { com.emc.storageos.db.client.model.StoragePort port = _dbClient.queryObject(com.emc.storageos.db.client.model.StoragePort.class, portUri); if (port.getStorageDevice().equals(storageSystemId) && !port.getInactive()) { storagePort = port; break; } } // Verify that discovered port has mandatory identifier "portNetworkId" if (driverPort.getPortNetworkId() == null) { if (storagePort == null) { _log.error("No portNetworkId for new discovered port {}, skip discovery of this port.", portNativeGuid); } else { _log.error("No portNetworkId for previously discovered port {}, skip discovery of this port.", portNativeGuid); } continue; } if (storagePort == null) { // New port processing storagePort = new com.emc.storageos.db.client.model.StoragePort(); prepareNewPort(storagePort, driverPort); storagePort.setNativeGuid(portNativeGuid); storagePort.setStorageDevice(storageSystemId); if (driverPort.getNetworkId() != null) { // Get or create Network object for this port Network portNetwork = getNetworkForStoragePort(driverPort); storagePort.setNetwork(portNetwork.getId()); // Add endpoint to the network. // Process this for all ports (existing port got a network or changed network cases) // TODO: should we check if existing port was in other network and delete the endpoint from the old network? portNetwork.addEndpoints(new ArrayList<>(Arrays.asList(driverPort.getPortNetworkId())), true); networksToUpdate.add(portNetwork); } storagePort.setTcpPortNumber(driverPort.getTcpPortNumber()); storagePort.setRegistrationStatus(DiscoveredDataObject.RegistrationStatus.REGISTERED.toString()); _log.info("Creating new storage port using NativeGuid : {}", portNativeGuid); newStoragePorts.add(storagePort); } else { existingStoragePorts.add(storagePort); } storagePort.setPortNetworkId(driverPort.getPortNetworkId()); if (driverPort.getTransportType()!= null && driverPort.getTransportType().equalsIgnoreCase(StoragePort.TransportType.IP.toString())) { storagePort.setIpAddress(driverPort.getIpAddress()); } storagePort.setDiscoveryStatus(DiscoveredDataObject.DiscoveryStatus.VISIBLE.name()); storagePort.setCompatibilityStatus(DiscoveredDataObject.CompatibilityStatus.COMPATIBLE.name()); storagePort.setOperationalStatus(driverPort.getOperationalStatus()); storagePort.setAvgBandwidth(driverPort.getAvgBandwidth()); storagePort.setPortSpeed(driverPort.getPortSpeed()); // Set usage metric for the port if (driverPort.getUtilizationMetric() != null) { StringMap usageMetrics = storagePort.getMetrics(); MetricsKeys.putDouble(MetricsKeys.portMetric, driverPort.getUtilizationMetric(), usageMetrics); storagePort.setMetrics(usageMetrics); } driverPortsToDBPorts.put(driverPort, storagePort); } storagePorts.put(NEW, newStoragePorts); storagePorts.put(EXISTING, existingStoragePorts); // Create storage ha domains for ports processStorageHADomains(storageSystem, Collections.unmodifiableMap(driverPortsToDBPorts)); } else { String errorMsg = String.format("Failed to discover storage ports for system %s of type %s. \n" + " Driver task message: %s", accessProfile.getSystemId(), accessProfile.getSystemType(), task.getMessage()); throw new ExternalDeviceCollectionException(false, ServiceCode.DISCOVERY_ERROR, null, errorMsg, null, null); } String message = String.format("Storage ports of storage array %s with native id %s were discovered successfully.", storageSystem.getId(), storageSystem.getNativeGuid()); _log.info(message); return storagePorts; } catch (Exception e) { String message = String.format("Failed to discover storage ports of storage array %s with native id %s : %s .", storageSystem.getId(), storageSystem.getNativeGuid(), e.getMessage()); _log.error(message, e); storageSystem.setLastDiscoveryStatusMessage(message); throw e; } finally { _dbClient.updateObject(storageSystem); _log.info("Discovery of storage ports of storage system {} of type {} - end", accessProfile.getSystemId(), accessProfile.getSystemType()); } } private void prepareNewPort(com.emc.storageos.db.client.model.StoragePort storagePort, StoragePort driverPort) { storagePort.setId(URIUtil.createId(com.emc.storageos.db.client.model.StoragePort.class)); storagePort.setIsDriverManaged(true); storagePort.setTransportType(driverPort.getTransportType()); storagePort.setNativeId(driverPort.getNativeId()); storagePort.setPortName(driverPort.getPortName()); storagePort.setLabel(driverPort.getPortName()); storagePort.setPortSpeed(driverPort.getPortSpeed()); storagePort.setPortGroup(driverPort.getPortGroup()); if (storagePort.getPortGroup() == null) { storagePort.setPortGroup(storagePort.getPortName()); } storagePort.setPortEndPointID(driverPort.getEndPointID()); _log.info("discoverPort: portNetworkId: {} ", storagePort.getPortNetworkId()); } public static StorageSystem initStorageSystem(com.emc.storageos.db.client.model.StorageSystem storageSystem) { StorageSystem driverStorageSystem = new StorageSystem(); driverStorageSystem.setNativeId(storageSystem.getNativeId()); driverStorageSystem.setIpAddress(storageSystem.getIpAddress()); driverStorageSystem.setSystemName(storageSystem.getLabel()); return driverStorageSystem; } /** * Returns Network object based on storage port information. * * @param driverPort [in] - storage port instance * @return Network object */ private Network getNetworkForStoragePort(StoragePort driverPort) { Network network; List<Network> results = CustomQueryUtility.queryActiveResourcesByAltId(_dbClient, Network.class, "nativeId", driverPort.getNetworkId()); if (results == null || results.isEmpty()) { network = new Network(); network.setId(URIUtil.createId(Network.class)); network.setTransportType(driverPort.getTransportType()); network.setNativeId(driverPort.getNetworkId()); network.setLabel(driverPort.getNetworkId()); network.setRegistrationStatus(DiscoveredDataObject.RegistrationStatus.REGISTERED.name()); network.setInactive(false); _dbClient.createObject(network); _log.info("Created a new network {}." , network.getLabel()); } else { network = results.get(0); } return network; } private void processStorageHADomains(com.emc.storageos.db.client.model.StorageSystem storageSystem, Map<StoragePort, com.emc.storageos.db.client.model.StoragePort> driverPortsToDBPorts) { // Map ha zone names to driver ports Map<String, Set<StoragePort>> haZoneNameToDriverPorts = new HashMap<>(); Set<StoragePort> driverPorts = driverPortsToDBPorts.keySet(); for (StoragePort driverPort : driverPorts) { if (driverPort.getPortHAZone() != null && !driverPort.getPortHAZone().isEmpty()) { Set<StoragePort> haZonePorts = haZoneNameToDriverPorts.get(driverPort.getPortHAZone()); if (haZonePorts == null) { haZonePorts = new HashSet<>(); haZoneNameToDriverPorts.put(driverPort.getPortHAZone(), haZonePorts); } haZonePorts.add(driverPort); } } for (Map.Entry<String, Set<StoragePort>> haZoneNameToDriverPort : haZoneNameToDriverPorts.entrySet()) { String portHAZone = haZoneNameToDriverPort.getKey(); Set<StoragePort> haZoneDriverPorts = haZoneNameToDriverPort.getValue(); if (portHAZone != null) { String haDomainNativeGUID = NativeGUIDGenerator.generateNativeGuid(storageSystem, portHAZone, NativeGUIDGenerator.ADAPTER); _log.info("HA Domain Native Guid : {}", haDomainNativeGUID); @SuppressWarnings("deprecation") List<URI> uriHaList = _dbClient.queryByConstraint(AlternateIdConstraint.Factory .getStorageHADomainByNativeGuidConstraint(haDomainNativeGUID)); StorageHADomain haDomain; if (uriHaList.isEmpty()) { haDomain = new StorageHADomain(); haDomain.setId(URIUtil.createId(StorageHADomain.class)); haDomain.setNativeGuid(haDomainNativeGUID); haDomain.setName(portHAZone); haDomain.setAdapterName(portHAZone); haDomain.setStorageDeviceURI(storageSystem.getId()); haDomain.setNumberofPorts(String.valueOf(haZoneDriverPorts.size())); _dbClient.createObject(haDomain); } else { haDomain = _dbClient.queryObject(StorageHADomain.class, uriHaList.get(0)); haDomain.setNumberofPorts(String.valueOf(haZoneDriverPorts.size())); _dbClient.updateObject(haDomain); } for (StoragePort driverPort : haZoneDriverPorts) { com.emc.storageos.db.client.model.StoragePort port = driverPortsToDBPorts.get(driverPort); port.setStorageHADomain(haDomain.getId()); } } } } }