/*
* Copyright (c) 2014 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.plugins;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.model.*;
import com.emc.storageos.db.client.model.DiscoveredDataObject.DiscoveryStatus;
import com.emc.storageos.db.client.util.CommonTransformerFunctions;
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.scaleio.ScaleIOException;
import com.emc.storageos.scaleio.api.restapi.ScaleIORestClient;
import com.emc.storageos.scaleio.api.restapi.response.ScaleIOProtectionDomain;
import com.emc.storageos.scaleio.api.restapi.response.ScaleIOSDC;
import com.emc.storageos.scaleio.api.restapi.response.ScaleIOSDS;
import com.emc.storageos.scaleio.api.restapi.response.ScaleIOSDS.IP;
import com.emc.storageos.scaleio.api.restapi.response.ScaleIOScsiInitiator;
import com.emc.storageos.scaleio.api.restapi.response.ScaleIOStoragePool;
import com.emc.storageos.scaleio.api.restapi.response.ScaleIOSystem;
import com.emc.storageos.scaleio.api.restapi.response.Slaves;
import com.emc.storageos.util.VersionChecker;
import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator;
import com.emc.storageos.volumecontroller.impl.StoragePoolAssociationHelper;
import com.emc.storageos.volumecontroller.impl.StoragePortAssociationHelper;
import com.emc.storageos.volumecontroller.impl.monitoring.cim.enums.OperationalStatus;
import com.emc.storageos.volumecontroller.impl.scaleio.ScaleIOHandleFactory;
import com.emc.storageos.volumecontroller.impl.utils.DiscoveryUtils;
import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.emc.storageos.db.client.util.CustomQueryUtility.queryActiveResourcesByAltId;
import static com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator.generateNativeGuid;
public class ScaleIOCommunicationInterface extends ExtendedCommunicationInterfaceImpl {
private static final Logger log = LoggerFactory.getLogger(ScaleIOCommunicationInterface.class);
private static final int LOCK_WAIT_SECONDS = 300;
private static final Set<String> SCALEIO_ONLY = Collections.singleton(HostInterface.Protocol.ScaleIO.name());
private static final Set<String> SCALEIO_AND_ISCSI = new HashSet<>();
private ScaleIOHandleFactory scaleIOHandleFactory;
static {
SCALEIO_AND_ISCSI.add(HostInterface.Protocol.ScaleIO.name());
SCALEIO_AND_ISCSI.add(HostInterface.Protocol.iSCSI.name());
}
public void setScaleIOHandleFactory(ScaleIOHandleFactory scaleIOHandleFactory) {
this.scaleIOHandleFactory = scaleIOHandleFactory;
this.scaleIOHandleFactory.setDbClient(_dbClient);
}
@Override
public void collectStatisticsInformation(AccessProfile accessProfile) throws BaseCollectionException {
}
@Override
public void scan(AccessProfile accessProfile) throws BaseCollectionException {
log.info("Starting scan of ScaleIO StorageProvider. IP={}", accessProfile.getIpAddress());
StorageProvider.ConnectionStatus cxnStatus = StorageProvider.ConnectionStatus.CONNECTED;
StorageProvider provider = _dbClient.queryObject(StorageProvider.class, accessProfile.getSystemId());
if (provider.getInterfaceType().equalsIgnoreCase(DiscoveredDataObject.Type.scaleio.name())) {
provider.setConnectionStatus(StorageProvider.ConnectionStatus.NOTCONNECTED.name());
ScaleIOException ex = ScaleIOException.exceptions.scaleioCliNotSupported();
provider.setLastScanStatusMessage(ex.getLocalizedMessage());
_dbClient.persistObject(provider);
throw ScaleIOException.exceptions.scaleioCliNotSupported();
}
_locker.acquireLock(accessProfile.getIpAddress(), LOCK_WAIT_SECONDS);
try {
ScaleIORestClient scaleIOHandle = scaleIOHandleFactory.using(_dbClient).getClientHandle(provider);
if (scaleIOHandle != null) {
Map<String, StorageSystemViewObject> storageSystemsCache = accessProfile.getCache();
ScaleIOSystem sioSystem = scaleIOHandle.getSystem();
String[] ipList = null;
if( sioSystem.getVersion().substring(0, 1).compareTo("2") >= 0 ){
Slaves[] slaves = sioSystem.getMdmCluster().getSlaves();
if( (slaves.length>0) )
ipList = new String[slaves.length];
for(int iterInd = 0 ; iterInd < slaves.length ; iterInd++){
ipList[iterInd] = slaves[iterInd].getIps()[0];
}
}
else{
ipList = sioSystem.getSecondaryMdmActorIpList();
}
if (ipList != null && ipList.length >0) {
StringSet secondaryIps = new StringSet();
secondaryIps.add(ipList[0]);
provider.setSecondaryIps(secondaryIps);
}
String scaleIOType = StorageSystem.Type.scaleio.name();
String installationId = sioSystem.getInstallId();
String version = sioSystem.getVersion().replaceAll("_", ".");
String minimumSupported = VersionChecker.getMinimumSupportedVersion(StorageSystem.Type.scaleio);
String compatibility = (VersionChecker.verifyVersionDetails(minimumSupported, version) < 0) ?
StorageSystem.CompatibilityStatus.INCOMPATIBLE.name() :
StorageSystem.CompatibilityStatus.COMPATIBLE.name();
provider.setCompatibilityStatus(compatibility);
provider.setVersionString(version);
List<ScaleIOProtectionDomain> protectionDomains = scaleIOHandle.getProtectionDomains();
for (ScaleIOProtectionDomain protectionDomain : protectionDomains) {
log.info("For ScaleIO instance {}, found ProtectionDomain {}", installationId, protectionDomain.getName());
String id = String.format("%s+%s", installationId, protectionDomain.getName());
String nativeGuid = generateNativeGuid(scaleIOType, id);
StorageSystemViewObject viewObject = storageSystemsCache.get(nativeGuid);
if (viewObject == null) {
viewObject = new StorageSystemViewObject();
}
viewObject.setDeviceType(scaleIOType);
viewObject.addprovider(accessProfile.getSystemId().toString());
viewObject.setProperty(StorageSystemViewObject.MODEL, "ScaleIO ECS");
viewObject.setProperty(StorageSystemViewObject.SERIAL_NUMBER, id);
storageSystemsCache.put(nativeGuid, viewObject);
}
}
} catch (Exception e) {
cxnStatus = StorageProvider.ConnectionStatus.NOTCONNECTED;
log.error(String.format("Exception was encountered when attempting to scan ScaleIO Instance %s",
accessProfile.getIpAddress()), e);
throw ScaleIOException.exceptions.scanFailed(e);
} finally {
provider.setConnectionStatus(cxnStatus.name());
_dbClient.persistObject(provider);
log.info("Completed scan of ScaleIO StorageProvider. IP={}", accessProfile.getIpAddress());
_locker.releaseLock(accessProfile.getIpAddress());
}
}
@Override
public void discover(AccessProfile accessProfile) throws BaseCollectionException {
StorageSystem.CompatibilityStatus compatibilityStatus = StorageSystem.CompatibilityStatus.COMPATIBLE;
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, accessProfile.getSystemId());
_locker.acquireLock(accessProfile.getIpAddress(), LOCK_WAIT_SECONDS);
log.info("Starting discovery of ScaleIO StorageProvider. IP={} StorageSystem {}",
accessProfile.getIpAddress(), storageSystem.getNativeGuid());
String statusMsg = "";
try {
ScaleIORestClient scaleIOHandle = scaleIOHandleFactory.using(_dbClient).getClientHandle(storageSystem);
if (scaleIOHandle != null) {
ScaleIOSystem sioSystem = scaleIOHandle.getSystem();
List<ScaleIOProtectionDomain> protectionDomains = scaleIOHandle.getProtectionDomains();
List<ScaleIOSDC> allSDCs = scaleIOHandle.queryAllSDC();
List<ScaleIOSDS> allSDSs = scaleIOHandle.queryAllSDS();
List<ScaleIOScsiInitiator> allSCSIInitiators = scaleIOHandle.queryAllSCSIInitiators();
List<StoragePort> ports = new ArrayList<>();
List<StoragePool> newPools = new ArrayList<StoragePool>();
List<StoragePool> updatePools = new ArrayList<StoragePool>();
List<StoragePool> allPools = new ArrayList<StoragePool>();
String scaleIOType = StorageSystem.Type.scaleio.name();
String installationId = sioSystem.getInstallId();
String version = sioSystem.getVersion().replaceAll("_", ".");
String minimumSupported = VersionChecker.getMinimumSupportedVersion(StorageSystem.Type.scaleio);
compatibilityStatus = (VersionChecker.verifyVersionDetails(minimumSupported, version) < 0) ?
StorageSystem.CompatibilityStatus.INCOMPATIBLE :
StorageSystem.CompatibilityStatus.COMPATIBLE;
storageSystem.setFirmwareVersion(version);
storageSystem.setCompatibilityStatus(compatibilityStatus.name());
storageSystem.setReachableStatus(true);
storageSystem.setLabel(storageSystem.getNativeGuid());
for (ScaleIOProtectionDomain protectionDomain : protectionDomains) {
String domainName = protectionDomain.getName();
String id = String.format("%s+%s", installationId, domainName);
String storageSystemNativeGUID = generateNativeGuid(scaleIOType, id);
if (!storageSystemNativeGUID.equals(storageSystem.getNativeGuid())) {
// This is not the ProtectionDomain that we're looking for
continue;
}
String protectionDomainId = protectionDomain.getId();
storageSystem.setSerialNumber(protectionDomainId);
Network network = createNetwork(installationId);
List<ScaleIOSDS> sdsList = new ArrayList<ScaleIOSDS>();
for (ScaleIOSDS sds : allSDSs) {
String pdId = sds.getProtectionDomainId();
if (pdId.equals(protectionDomainId)) {
sdsList.add(sds);
}
}
List<StoragePort> thesePorts =
createStoragePorts(storageSystem, compatibilityStatus.name(), network, sdsList, domainName);
ports.addAll(thesePorts);
createHost(network, allSDCs);
boolean hasSCSIInitiators =
createSCSIInitiatorsAndStoragePorts(storageSystem, domainName, compatibilityStatus,
installationId, allSCSIInitiators, allSDCs, ports);
List<StoragePort> notVisiblePorts = DiscoveryUtils.checkStoragePortsNotVisible(ports, _dbClient,
storageSystem.getId());
if (notVisiblePorts != null && !notVisiblePorts.isEmpty()) {
ports.addAll(notVisiblePorts);
}
Set<String> supportedProtocols = (hasSCSIInitiators) ? SCALEIO_AND_ISCSI : SCALEIO_ONLY;
List<ScaleIOStoragePool> storagePools = scaleIOHandle.getProtectionDomainStoragePools(protectionDomainId);
for (ScaleIOStoragePool storagePool : storagePools) {
String poolName = storagePool.getName();
String nativeGuid = String.format("%s-%s-%s", installationId, domainName, poolName);
log.info("Attempting to discover pool {} for ProtectionDomain {}", poolName, domainName);
List<StoragePool> pools =
queryActiveResourcesByAltId(_dbClient, StoragePool.class, "nativeGuid", nativeGuid);
StoragePool pool = null;
if (pools.isEmpty()) {
log.info("Pool {} is new", poolName);
pool = new StoragePool();
pool.setId(URIUtil.createId(StoragePool.class));
pool.setStorageDevice(accessProfile.getSystemId());
pool.setPoolServiceType(StoragePool.PoolServiceType.block.toString());
pool.setOperationalStatus(StoragePool.PoolOperationalStatus.READY.name());
pool.setCompatibilityStatus(compatibilityStatus.name());
pool.setThinVolumePreAllocationSupported(false);
pool.addDriveTypes(Collections.singleton(StoragePool.SupportedDriveTypeValues.SATA.name()));
StringSet copyTypes = new StringSet();
copyTypes.add(StoragePool.CopyTypes.ASYNC.name());
copyTypes.add(StoragePool.CopyTypes.UNSYNC_UNASSOC.name());
pool.setSupportedCopyTypes(copyTypes);
pool.setMaximumThickVolumeSize(1048576L);
pool.setMinimumThickVolumeSize(1L);
newPools.add(pool);
} else if (pools.size() == 1) {
log.info("Pool {} was previously discovered", storagePool);
pool = pools.get(0);
updatePools.add(pool);
} else {
log.warn(String.format("There are %d StoragePools with nativeGuid = %s", pools.size(),
nativeGuid));
continue;
}
pool.setPoolName(poolName);
pool.setNativeId(storagePool.getId());
pool.setNativeGuid(nativeGuid);
String availableCapacityString = storagePool.getCapacityAvailableForVolumeAllocationInKb();
pool.setFreeCapacity(Long.parseLong(availableCapacityString));
String totalCapacityString = storagePool.getMaxCapacityInKb();
pool.setTotalCapacity(Long.parseLong(totalCapacityString));
pool.addProtocols(supportedProtocols);
pool.setSupportedResourceTypes(StoragePool.SupportedResourceTypes.THIN_AND_THICK.name());
Long maxThinSize = 1048576L;
Long minThinSize = 1L;
pool.setMaximumThinVolumeSize(maxThinSize);
pool.setMinimumThinVolumeSize(minThinSize);
pool.setInactive(false);
pool.setDiscoveryStatus(DiscoveryStatus.VISIBLE.name());
}
}
log.info(String.format("For StorageSystem %s, discovered %d new pools and %d pools to update",
storageSystem.getNativeGuid(), newPools.size(), updatePools.size()));
StoragePoolAssociationHelper.setStoragePoolVarrays(storageSystem.getId(), newPools, _dbClient);
allPools.addAll(newPools);
allPools.addAll(updatePools);
_dbClient.createObject(newPools);
_dbClient.updateAndReindexObject(updatePools);
List<StoragePool> notVisiblePools = DiscoveryUtils.checkStoragePoolsNotVisible(allPools, _dbClient,
storageSystem.getId());
if (notVisiblePools != null && !notVisiblePools.isEmpty()) {
allPools.addAll(notVisiblePools);
}
StoragePortAssociationHelper.runUpdatePortAssociationsProcess(ports, null, _dbClient, _coordinator, allPools);
statusMsg = String.format("Discovery completed successfully for Storage System: %s",
storageSystem.getNativeGuid());
}
} catch (Exception e) {
storageSystem.setReachableStatus(false);
log.error(String.format("Exception was encountered when attempting to discover ScaleIO Instance %s",
accessProfile.getIpAddress()), e);
statusMsg = String.format("Discovery failed because %s", e.getLocalizedMessage());
throw ScaleIOException.exceptions.discoveryFailed(e);
} finally {
_locker.releaseLock(accessProfile.getIpAddress());
if (storageSystem != null) {
storageSystem.setLastDiscoveryStatusMessage(statusMsg);
}
}
_dbClient.updateAndReindexObject(storageSystem);
log.info("Completed of ScaleIO StorageProvider. IP={} StorageSystem {}",
accessProfile.getIpAddress(), storageSystem.getNativeGuid());
}
/**
* Create a Host object for every SDC that is found on the system. Create a single
* initiator for the host in the specified Network.
*
* @param network [in] Network object to associated the hosts' initiator ports
* @param queryAllSDCResult [in] - SDC query result
*/
private void createHost(Network network, List<ScaleIOSDC> allSDCs) {
// Find the root tenant and associate any SDC hosts with it
List<URI> tenantOrgList = _dbClient.queryByType(TenantOrg.class, true);
Iterator<TenantOrg> it = _dbClient.queryIterativeObjects(TenantOrg.class, tenantOrgList);
List<String> initiatorsToAddToNetwork = new ArrayList<>();
URI rootTenant = null;
while (it.hasNext()) {
TenantOrg tenantOrg = it.next();
if (TenantOrg.isRootTenant(tenantOrg)) {
rootTenant = tenantOrg.getId();
break;
}
}
for (ScaleIOSDC sdc : allSDCs) {
String ip = sdc.getSdcIp();
String guid = sdc.getSdcGuid();
// First we search by nativeGuid
Host host = findByNativeGuid(guid);
if (host == null) {
// Host with nativeGuid is not known to ViPR, try and find by IP address
host = findOrCreateByIp(rootTenant, ip, guid);
}
// Create an single initiator for this SDC. If the initiator has already been
// created, the existing Initiator will be returned. Associate the initiator
// with the network
Initiator initiator = createInitiator(host, ip, sdc.getId());
if (!network.hasEndpoint(initiator.getInitiatorPort())) {
initiatorsToAddToNetwork.add(initiator.getInitiatorPort());
}
}
if (!initiatorsToAddToNetwork.isEmpty()) {
network.addEndpoints(initiatorsToAddToNetwork, true);
_dbClient.updateAndReindexObject(network);
}
}
private Host findByNativeGuid(String guid) {
List<Host> resultsByGuid =
CustomQueryUtility.
queryActiveResourcesByAltId(_dbClient, Host.class, "nativeGuid", guid);
if (resultsByGuid == null || resultsByGuid.isEmpty()) {
return null;
}
return resultsByGuid.get(0);
}
private Host findOrCreateByIp(URI rootTenant, String ip, String guid) {
List<IpInterface> resultsByIp =
CustomQueryUtility.
queryActiveResourcesByAltId(_dbClient, IpInterface.class, "ipAddress", ip);
Host host = null;
if (resultsByIp == null || resultsByIp.isEmpty()) {
host = findHostByHostName(ip);
if (host == null) {
log.info(String.format("Could not find any existing Host with IpInterface or Hostname %s. " +
"Creating new Host for SDC %s", ip, guid));
// Host with IP address not found, need to create it
host = new Host();
host.setId(URIUtil.createId(Host.class));
host.setHostName(ip);
host.setTenant(rootTenant);
host.setType(DiscoveredDataObject.Type.host.name());
host.setLabel(ip);
host.setNativeGuid(guid);
host.setType(Host.HostType.Other.name());
host.setDiscoverable(false);
host.setDiscoveryStatus(DiscoveredDataObject.DataCollectionJobStatus.COMPLETE.name());
host.setCompatibilityStatus(DiscoveredDataObject.CompatibilityStatus.COMPATIBLE.name());
host.setSuccessDiscoveryTime(System.currentTimeMillis());
host.setInactive(false);
_dbClient.createObject(host);
}
} else {
// Host with IP address was found, need to update it with nativeGuid unless it's already set.
IpInterface ipInterface = resultsByIp.get(0);
host = _dbClient.queryObject(Host.class, ipInterface.getHost());
if (host != null && Strings.isNullOrEmpty(host.getNativeGuid())) {
log.info(String.format("Existing Host %s (%s) found and will be used as container for SDC %s",
ip, host.getNativeGuid(), guid));
host.setNativeGuid(guid);
_dbClient.updateAndReindexObject(host);
} else {
log.warn(String.format("Found an IpInterface %s, but its associated Host %s could not be found.",
ip, ipInterface.getHost()));
}
}
return host;
}
private Host findHostByHostName(String ip) {
Host host = null;
List<Host> results =
CustomQueryUtility.
queryActiveResourcesByAltId(_dbClient, Host.class, "hostName", ip);
if (results != null && !results.isEmpty()) {
Collection<URI> hostIdStrings = Collections2.transform(results,
CommonTransformerFunctions.fctnDataObjectToID());
log.info(String.format("Found %d hosts with ip %s as their hostName: %s",
results.size(), ip, CommonTransformerFunctions.collectionToString(hostIdStrings)));
host = results.get(0);
}
return host;
}
/**
* Create initiator for the specified host
*
* @param host [in] - Host object reference
* @param ip [in] - IP address string
* @param id [id] - Indentifier for the port
* @return Initiator object
*/
private Initiator createInitiator(Host host, String ip, String id) {
Initiator initiator;
List<Initiator> results =
CustomQueryUtility.queryActiveResourcesByAltId(_dbClient, Initiator.class, "iniport", id);
if (results == null || results.isEmpty()) {
initiator = new Initiator();
initiator.setId(URIUtil.createId(Initiator.class));
initiator.setHost(host.getId());
initiator.setHostName(ip);
initiator.setInitiatorPort(id);
initiator.setProtocol(HostInterface.Protocol.ScaleIO.name());
initiator.setRegistrationStatus(DiscoveredDataObject.RegistrationStatus.REGISTERED.name());
initiator.setInactive(false);
_dbClient.createObject(initiator);
} else {
initiator = results.get(0);
}
return initiator;
}
/**
* This will create an IP network for the SIO system to contain the iSCSI initiators
* associated with the system (if any). It will also create the iSCSI initiators and
* StoragePorts, placing them in the IP network.
*
* @param storageSystem [in] - StorageSystem object (ProtectionDomain)
* @param protectionDomainName [in] - Protection Domain name
* @param compatibilityStatus [in] - Compatibility status to use on the ports
* @param installationId [in] - Installation ID unique to ScaleIO instance
* @param queryAllSCSIInitiatorsResult [in] - Result of querying ScaleIO for SCSI initiators
* @param queryAllSDCResult [in] - Result of querying ScaleIO for SDC clients
* @param ports [out] - List to update with iSCSI StoragePorts that were discovered
* @return - true if there were SCSI initiators found on the system.
* @throws IOException
*/
private boolean createSCSIInitiatorsAndStoragePorts(StorageSystem storageSystem, String protectionDomainName,
DiscoveredDataObject.CompatibilityStatus compatibilityStatus,
String installationId,
List<ScaleIOScsiInitiator> allSCSIInitiators,
List<ScaleIOSDC> allSDCs, List<StoragePort> ports) throws IOException {
boolean hasSCSIInitiators = false;
if (allSDCs != null && allSCSIInitiators != null && !allSCSIInitiators.isEmpty()) {
List<String> initiatorsToAddToNetwork = new ArrayList<>();
String networkId = String.format("%s-IP", installationId);
Network networkForSCSIInitiators = createIPNetworkForSCSIInitiators(networkId);
for (ScaleIOScsiInitiator scsiInit : allSCSIInitiators) {
String id = scsiInit.getId();
String iqn = scsiInit.getIqn();
Initiator initiator = createSCSIInitiator(iqn, id);
if (!networkForSCSIInitiators.hasEndpoint(initiator.getInitiatorPort())) {
initiatorsToAddToNetwork.add(initiator.getInitiatorPort());
}
hasSCSIInitiators = true;
}
if (!initiatorsToAddToNetwork.isEmpty()) {
networkForSCSIInitiators.addEndpoints(initiatorsToAddToNetwork, true);
_dbClient.updateAndReindexObject(networkForSCSIInitiators);
}
List<StoragePort> iSCSIPorts =
createSCSIStoragePorts(storageSystem, protectionDomainName, compatibilityStatus,
networkForSCSIInitiators, allSDCs);
ports.addAll(iSCSIPorts);
}
return hasSCSIInitiators;
}
/**
* Create an IP Network object for iSCSI initiators.
*
* @param uniqueId [in] - Unique string identifier for the network
* @return Network object
*/
private Network createIPNetworkForSCSIInitiators(String uniqueId) {
Network network;
List<Network> results =
CustomQueryUtility.queryActiveResourcesByAltId(_dbClient, Network.class, "nativeId", uniqueId);
if (results == null || results.isEmpty()) {
network = new Network();
network.setId(URIUtil.createId(Network.class));
network.setTransportType(StorageProtocol.Transport.IP.name());
network.setNativeId(uniqueId);
network.setLabel(String.format("%s-ScaleIONetwork", uniqueId));
network.setRegistrationStatus(DiscoveredDataObject.RegistrationStatus.REGISTERED.name());
network.setInactive(false);
_dbClient.createObject(network);
} else {
network = results.get(0);
}
return network;
}
/**
* Create iSCSI initiator for the specified host
*
* @param iqn [id] - iSCSI IQN for the port
* @return Initiator object
*/
private Initiator createSCSIInitiator(String iqn, String id) {
Initiator initiator;
List<Initiator> results =
CustomQueryUtility.queryActiveResourcesByAltId(_dbClient, Initiator.class, "iniport", iqn);
if (results == null || results.isEmpty()) {
initiator = new Initiator();
initiator.setId(URIUtil.createId(Initiator.class));
initiator.setInitiatorPort(iqn);
initiator.setProtocol(HostInterface.Protocol.iSCSI.name());
initiator.setRegistrationStatus(DiscoveredDataObject.RegistrationStatus.REGISTERED.name());
initiator.setInactive(false);
if (id != null && !id.isEmpty()) {
initiator.setLabel(id);
}
_dbClient.createObject(initiator);
} else {
initiator = results.get(0);
initiator.setLabel(id);
_dbClient.persistObject(initiator);
}
return initiator;
}
/**
* Create a Network object for the ScaleIO instance and associate it with the VArray
*
* @param uniqueId [in] - Unique string identifier for the network
* @return Network object
*/
private Network createNetwork(String uniqueId) {
Network network;
List<Network> results =
CustomQueryUtility.queryActiveResourcesByAltId(_dbClient, Network.class, "nativeId", uniqueId);
if (results == null || results.isEmpty()) {
network = new Network();
network.setId(URIUtil.createId(Network.class));
network.setTransportType(StorageProtocol.Transport.ScaleIO.name());
network.setNativeId(uniqueId);
network.setLabel(String.format("%s-ScaleIONetwork", uniqueId));
network.setRegistrationStatus(DiscoveredDataObject.RegistrationStatus.REGISTERED.name());
network.setInactive(false);
_dbClient.createObject(network);
} else {
network = results.get(0);
}
return network;
}
/**
* Create a StoragePort for each SDS in the ScaleIO instance. These are psuedo-StoragePorts
* for the purpose of tying up the host-end to the storage-end of the Network
*
* @param storageSystem [in] - StorageSystem object (ProtectionDomain)
* @param compatibilityStatus [in] - Compatibility status to use on the ports
* @param network [in] - Network to associate with the ports
* @param queryAllSDSResult [in] - SDS query result
* @param protectionDomainName [in] - Protection Domain name
*/
private List<StoragePort> createStoragePorts(StorageSystem storageSystem, String compatibilityStatus, Network network,
List<ScaleIOSDS> allSDSs, String protectionDomainName) throws IOException {
List<StoragePort> ports = new ArrayList<>();
List<String> endpoints = new ArrayList<>();
for (ScaleIOSDS sds : allSDSs) {
String sdsId = sds.getId();
List<IP> ips = sds.getIpList();
String sdsIP = null;
if (ips != null && !ips.isEmpty()) {
sdsIP = ips.get(0).getIp();
}
StoragePort port;
List<StoragePort> results = CustomQueryUtility.
queryActiveResourcesByAltId(_dbClient, StoragePort.class, "portNetworkId", sdsId);
if (results == null || results.isEmpty()) {
String nativeGUID =
NativeGUIDGenerator.generateNativeGuid(storageSystem,
protectionDomainName, NativeGUIDGenerator.ADAPTER);
StorageHADomain adapter = new StorageHADomain();
adapter.setStorageDeviceURI(storageSystem.getId());
adapter.setId(URIUtil.createId(StorageHADomain.class));
adapter.setAdapterName(protectionDomainName);
adapter.setLabel(protectionDomainName);
adapter.setNativeGuid(nativeGUID);
adapter.setNumberofPorts("1");
adapter.setAdapterType(StorageHADomain.HADomainType.FRONTEND.name());
adapter.setInactive(false);
_dbClient.createObject(adapter);
port = new StoragePort();
port.setId(URIUtil.createId(StoragePort.class));
port.setPortNetworkId(sdsId);
port.setLabel(String.format("%s-%s-StoragePort", protectionDomainName, sdsId));
port.setStorageDevice(storageSystem.getId());
port.setCompatibilityStatus(compatibilityStatus);
port.setOperationalStatus(OperationalStatus.OK.name());
port.setIpAddress(sdsIP);
port.setNetwork(network.getId());
port.setPortGroup(sdsId);
port.setPortName(sdsId);
port.setPortType(StoragePort.PortType.frontend.name());
port.setStorageHADomain(adapter.getId());
port.setTransportType(StorageProtocol.Transport.ScaleIO.name());
port.setDiscoveryStatus(DiscoveryStatus.VISIBLE.name());
port.setInactive(false);
_dbClient.createObject(port);
endpoints.add(port.getPortNetworkId());
} else {
port = results.get(0);
}
ports.add(port);
}
network.addEndpoints(endpoints, true);
_dbClient.updateAndReindexObject(network);
return ports;
}
/**
* Create an iSCSI StoragePort for each SDC in the ScaleIO instance. The SDC would present iSCSI
* targets to iSCSI initiators. These are psuedo-StoragePorts or the purpose of tying up
* the host-end to the storage-end of the IP Network
* <p/>
* Note about StoragePorts created here: The iSCSI target ports are generated and created per StorageSystem, keeping them in line with
* other arrays. However, ScaleIO itself has a different way of presenting the targets. The targets are actually on the SDC client hosts
* -- any SDC client in the ScaleIO system that has the SCSI software running on it will be able to present an iSCSI target to an iSCSI
* initiator. The name of this target will take the form of iqn.2010-12.com.ecs:[SDC GUID]. In order for ViPR to support multiple using
* multiple StorageSystems (ProtectionDomains) using the same set of SDC, we have to invent targets per ProtectionDomain. This means
* that we will created a slightly modified IDQ to distinguish between them: iqn.2010-12.com.ecs.[PD name]:[SDC GUID]. Having such an
* implementation does not affect the volume export because ScaleIO does not require specifying the target.
*
* @param storageSystem [in] - StorageSystem object (ProtectionDomain)
* @param compatibilityStatus [in] - Compatibility status to use on the ports
* @param network [in] - Network to associate with the ports
* @param queryAllSDCResult [in] - SDS query result
*/
private List<StoragePort> createSCSIStoragePorts(StorageSystem storageSystem, String protectionDomainName,
DiscoveredDataObject.CompatibilityStatus compatibilityStatus,
Network network, List<ScaleIOSDC> allSDCs)
throws IOException {
List<StoragePort> ports = new ArrayList<>();
List<String> endpoints = new ArrayList<>();
String fixedProtectionDomainName = protectionDomainName.replaceAll("\\s+", "").toLowerCase();
for (ScaleIOSDC sdc : allSDCs) {
String sdcGUID = sdc.getSdcGuid();
String sdcIP = sdc.getSdcIp();
String generatedTargetName = String.format("iqn.2010-12.com.ecs.%s:%s", fixedProtectionDomainName,
sdcGUID.toLowerCase());
StoragePort port;
List<StoragePort> results = CustomQueryUtility.
queryActiveResourcesByAltId(_dbClient, StoragePort.class, "portNetworkId", generatedTargetName);
if (results == null || results.isEmpty()) {
String nativeGUID =
NativeGUIDGenerator.generateNativeGuid(storageSystem,
sdcIP, NativeGUIDGenerator.ADAPTER);
StorageHADomain adapter = new StorageHADomain();
adapter.setStorageDeviceURI(storageSystem.getId());
adapter.setId(URIUtil.createId(StorageHADomain.class));
adapter.setAdapterName(sdcIP);
adapter.setLabel(sdcIP);
adapter.setNativeGuid(nativeGUID);
adapter.setNumberofPorts("1");
adapter.setAdapterType(StorageHADomain.HADomainType.FRONTEND.name());
adapter.setInactive(false);
_dbClient.createObject(adapter);
port = new StoragePort();
port.setId(URIUtil.createId(StoragePort.class));
port.setPortNetworkId(generatedTargetName);
port.setLabel(generatedTargetName);
port.setStorageDevice(storageSystem.getId());
port.setCompatibilityStatus(compatibilityStatus.name());
port.setOperationalStatus(OperationalStatus.OK.name());
port.setIpAddress(sdcIP);
port.setNetwork(network.getId());
port.setPortGroup("");
port.setPortName(generatedTargetName);
port.setPortType(StoragePort.PortType.frontend.name());
port.setStorageHADomain(adapter.getId());
port.setTransportType(StorageProtocol.Transport.IP.name());
port.setInactive(false);
port.setDiscoveryStatus(DiscoveryStatus.VISIBLE.name());
_dbClient.createObject(port);
endpoints.add(port.getPortNetworkId());
} else {
port = results.get(0);
}
ports.add(port);
}
network.addEndpoints(endpoints, true);
_dbClient.updateAndReindexObject(network);
return ports;
}
}