/*
* Copyright (c) 2008-2011 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.plugins.discovery.smis.processor;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.cim.CIMInstance;
import javax.cim.CIMObjectPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.coordinator.client.service.CoordinatorClient;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.model.StoragePool;
import com.emc.storageos.db.client.model.StoragePort;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.StoragePort.OperationalStatus;
import com.emc.storageos.plugins.AccessProfile;
import com.emc.storageos.plugins.BaseCollectionException;
import com.emc.storageos.plugins.common.Constants;
import com.emc.storageos.plugins.common.domainmodel.Operation;
import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator;
import com.emc.storageos.volumecontroller.impl.StoragePoolAssociationHelper;
import com.google.common.base.Joiner;
public class StorageProtocolEndPointProcessor extends StorageEndPointProcessor {
private Logger _logger = LoggerFactory
.getLogger(StorageProtocolEndPointProcessor.class);
private List<Object> args;
private DbClient _dbClient;
private static final String NAME = "Name";
private static final String SYSTEMNAME = "SystemName";
private static final String DEVICEID = "DeviceID";
private static final String COMMA_STR = ",";
@Override
public void processResult(
Operation operation, Object resultObj, Map<String, Object> keyMap)
throws BaseCollectionException {
try {
@SuppressWarnings("unchecked")
final Iterator<CIMInstance> it = (Iterator<CIMInstance>) resultObj;
_dbClient = (DbClient) keyMap.get(Constants.dbClient);
CoordinatorClient coordinator = (CoordinatorClient) keyMap.get(Constants.COORDINATOR_CLIENT);
AccessProfile profile = (AccessProfile) keyMap.get(Constants.ACCESSPROFILE);
Map<URI, StoragePool> poolsToMatchWithVpool = (Map<URI, StoragePool>) keyMap.get(Constants.MODIFIED_STORAGEPOOLS);
StorageSystem device = _dbClient.queryObject(StorageSystem.class, profile.getSystemId());
List<StoragePort> newPorts = new ArrayList<StoragePort>();
List<StoragePort> existingPorts = new ArrayList<StoragePort>();
while (it.hasNext()) {
CIMInstance endPointInstance = null;
StoragePort port = null;
try {
endPointInstance = it.next();
String portInstanceID = endPointInstance.getObjectPath()
.getKey(SYSTEMNAME).getValue().toString();
if (device.checkIfVmax3()) {
CIMObjectPath logicalPortPath = getObjectPathfromCIMArgument(args);
// We need the portInstanceID to not constitute the Virtual information.
// i.e Instead of SYMMETRIX-+-<<SERIAL>>-+-115-+-0 it should be SYMMETRIX-+-<<SERIAL>>-+-SE-1G-+-0
StringBuffer newPortInstanceID = new StringBuffer(logicalPortPath.getKey(SYSTEMNAME).getValue().toString());
newPortInstanceID.append(Constants._plusDelimiter)
.append(logicalPortPath.getKey(DEVICEID).getValue().toString());
portInstanceID = (newPortInstanceID.toString()).replaceAll(Constants.SMIS_PLUS_REGEX,
Constants.SMIS80_DELIMITER_REGEX);
}
String iScsiPortName = getCIMPropertyValue(endPointInstance, NAME);
// Skip the iSCSI ports without name or without a valid name.
if (null == iScsiPortName || iScsiPortName.split(COMMA_STR)[0].length() <= 0) {
_logger.warn("Invalid port Name found for {} Skipping", portInstanceID);
continue;
}
port = checkEthernetStoragePortExistsInDB(
iScsiPortName.split(COMMA_STR)[0].toLowerCase(), _dbClient, device);
createEthernetStoragePort(keyMap, port, endPointInstance,
portInstanceID, coordinator, newPorts, existingPorts);
addPath(keyMap, operation.getResult(),
endPointInstance.getObjectPath());
} catch (Exception e) {
_logger.warn("SCSI End Point Discovery failed for {}-->{}", "",
getMessage(e));
}
}
@SuppressWarnings("unchecked")
List<List<StoragePort>> portsUsedToRunNetworkConnectivity = (List<List<StoragePort>>) keyMap.get(Constants.STORAGE_PORTS);
portsUsedToRunNetworkConnectivity.add(newPorts);
// discovered ports used later to check for not visible ports
List<StoragePort> discoveredPorts = (List<StoragePort>) keyMap.get(Constants.DISCOVERED_PORTS);
discoveredPorts.addAll(newPorts);
discoveredPorts.addAll(existingPorts);
List<StoragePool> modifiedPools = StoragePoolAssociationHelper.getStoragePoolsFromPorts(_dbClient, newPorts, null);
for (StoragePool pool : modifiedPools) {
// pool matcher will be invoked on this pool
if (!poolsToMatchWithVpool.containsKey(pool.getId())) {
poolsToMatchWithVpool.put(pool.getId(), pool);
}
}
_logger.debug("# Pools used in invoking PoolMatcher during StorageProtoclEndPoint {}",
Joiner.on("\t").join(poolsToMatchWithVpool.keySet()));
} catch (Exception e) {
_logger.error("SCSI End Point Discovery failed -->{}", getMessage(e));
}
}
/**
* create Ethernet Storage Port.
* StoragePorts would have been created in SToragePorts Processor, but for ethernet those
* will not get updated to DB, as to get SCSIAddress ,we need a different SMI Class ProtocolEndPoint
* Algo :
* 1. Check if StorageEthernet Port available in DB.
* 2. If not, then get already created StoragePort, update SCSI Address and persist.
* 3. If yes, then just update the properties alone.
*
* @param keyMap
* @param port
* @param endPointInstance
* @param portInstanceID
* @throws IOException
*/
private void createEthernetStoragePort(
Map<String, Object> keyMap, StoragePort port, CIMInstance endPointInstance,
String portInstanceID, CoordinatorClient coordinator, List<StoragePort> newPorts,
List<StoragePort> existingPorts) throws IOException {
StoragePort portinMemory = (StoragePort) keyMap.get(portInstanceID);
String endPointInstanceId = endPointInstance.getObjectPath().getKey(NAME)
.getValue().toString().split(COMMA_STR)[0].toLowerCase();
if (null == port) {
if ((portinMemory != null) && (portinMemory.getPortNetworkId() != null) &&
!(portinMemory.getPortNetworkId().equals(endPointInstanceId))) {
// Since this is a new protocol endpoint and for V3, a single physical port can have multiple
// virtualiSCSIProtocolEndpoints, we will need to create new port object
StoragePort newPortinMemory = portinMemory.clone();
newPortinMemory.setId(URIUtil.createId(StoragePort.class));
newPortinMemory.setPortNetworkId(endPointInstanceId);
newPortinMemory.setPortEndPointID(endPointInstance.getObjectPath().getKey(NAME)
.getValue().toString());
String portNativeGuid = NativeGUIDGenerator.generateNativeGuid(_dbClient, newPortinMemory);
newPortinMemory.setNativeGuid(portNativeGuid);
newPortinMemory.setLabel(portNativeGuid);
_logger.info("Creating port - {}:{}", newPortinMemory.getLabel(), newPortinMemory.getNativeGuid());
_dbClient.createObject(newPortinMemory);
newPorts.add(newPortinMemory);
} else {
// Name Property's value --> iqn.23.....,t,0x0001
portinMemory.setPortNetworkId(endPointInstanceId);
portinMemory.setPortEndPointID(endPointInstance.getObjectPath().getKey(NAME)
.getValue().toString());
String portNativeGuid = NativeGUIDGenerator.generateNativeGuid(_dbClient, portinMemory);
portinMemory.setNativeGuid(portNativeGuid);
portinMemory.setLabel(portNativeGuid);
_logger.info("Creating port - {}:{}", portinMemory.getLabel(), portinMemory.getNativeGuid());
_dbClient.createObject(portinMemory);
newPorts.add(portinMemory);
}
} else {
String currentPortName = port.getPortName();
if (!currentPortName.contains(portinMemory.getPortName())) {
// A single VirtualiSCSIProtocolEndpoint is associated to multiple physical GIGE ports
StringBuffer appendedPortName = new StringBuffer(currentPortName);
appendedPortName.append(COMMA_STR).append(portinMemory.getPortName());
port.setPortName(appendedPortName.toString());
}
port.setPortSpeed(portinMemory.getPortSpeed());
port.setPortEndPointID(endPointInstance.getObjectPath().getKey(NAME)
.getValue().toString());
port.setCompatibilityStatus(portinMemory.getCompatibilityStatus());
port.setDiscoveryStatus(portinMemory.getDiscoveryStatus());
if (!OperationalStatus.OK.name().equals(port.getOperationalStatus())) {
port.setOperationalStatus(portinMemory.getOperationalStatus());
}
_logger.info("Updating port - {} : {}", port.getLabel(), port.getNativeGuid());
_dbClient.persistObject(port);
existingPorts.add(port);
}
}
@Override
protected void setPrerequisiteObjects(List<Object> inputArgs)
throws BaseCollectionException {
args = inputArgs;
}
}