/*
* Copyright 2016 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.hp3par.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.mutable.MutableBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.hp3par.command.FcPath;
import com.emc.storageos.hp3par.command.HostCommandResult;
import com.emc.storageos.hp3par.command.HostMember;
import com.emc.storageos.hp3par.command.HostSetDetailsCommandResult;
import com.emc.storageos.hp3par.command.ISCSIPath;
import com.emc.storageos.hp3par.command.Position;
import com.emc.storageos.hp3par.command.VirtualLun;
import com.emc.storageos.hp3par.command.VirtualLunsList;
import com.emc.storageos.hp3par.command.VlunResult;
import com.emc.storageos.hp3par.utils.CompleteError;
import com.emc.storageos.hp3par.utils.HP3PARConstants;
import com.emc.storageos.hp3par.utils.HP3PARUtil;
import com.emc.storageos.hp3par.utils.SanUtils;
import com.emc.storageos.storagedriver.DriverTask;
import com.emc.storageos.storagedriver.LockManager;
import com.emc.storageos.storagedriver.Registry;
import com.emc.storageos.storagedriver.model.Initiator;
import com.emc.storageos.storagedriver.model.StoragePort;
import com.emc.storageos.storagedriver.model.StorageVolume;
import com.emc.storageos.storagedriver.model.Initiator.HostOsType;
import com.emc.storageos.storagedriver.model.Initiator.Type;
import com.emc.storageos.storagedriver.model.StoragePool.Protocols;
import com.emc.storageos.storagedriver.storagecapabilities.StorageCapabilities;
/**
*
* Implements export/unexport operations
*
*/
public class HP3PARExpUnexpHelper {
private static final Logger _log = LoggerFactory.getLogger(HP3PARExpUnexpHelper.class);
private HP3PARUtil hp3parUtil;
/*********USE CASES**********
EXCLUSIVE EXPORT: Will include port number of host
1 Export volume to existing host
2 Export volume to non-existing host
3 Add initiator to existing host
4 Remove initiator from host
5 Unexport volume
A 1-5 can be done with single/multiple volumes,initiators as applicable
B Does not depend on host name
C Adding an initiator in matched-set will not do anything further.
All volumes have to be exported to new initiator explicitly.
In host-sees 3PAR will automatically export the volumes to newly added initiator.
-------------------------------------------
SHARED EXPORT: Will not include port number, exported to all ports, the cluster can see
1 Export volume to existing cluster
2 Export volume to non-existing cluster
3 Add initiator to existing host in cluster
4 Remove initiator from host in cluster
5 Unexport volume from cluster
6 Export a private volume to a host in a cluster
7 Unexport a private volume from a host in a cluster
8 Add a host to cluster
9 Remove a host from a cluster
10 Add a host having private export
11 Remove a host having private export
12 Move a host from one cluster to another
A 1-12 can be done with single/multiple volumes,initiators,hosts as applicable
B Cluster name in ViPR and 3PAR has to be identical with case
C Adding a new host to host-set will automatically export all volumes to the new host(initial export must have been host-set)
*/
/*
* All volumes in the list will be exported to all initiators using recommended ports. If a volume can not be exported to 'n'
* initiators the same will be tried with available ports
*/
public DriverTask exportVolumesToInitiators(List<Initiator> initiators, List<StorageVolume> volumes,
Map<String, String> volumeToHLUMap, List<StoragePort> recommendedPorts, List<StoragePort> availablePorts,
StorageCapabilities capabilities, MutableBoolean usedRecommendedPorts, List<StoragePort> selectedPorts,
DriverTask task, Registry driverRegistry, LockManager driverLockManager) {
_log.info("3PARDriver:exportVolumesToInitiators enter");
String host = null;
host = doHostProcessing(initiators, volumes, driverRegistry, driverLockManager);
if (host == null ) {
task.setMessage("exportVolumesToInitiators error: Processing hosts, Unable to export");
task.setStatus(DriverTask.TaskStatus.FAILED);
return task;
}
/*
Export will be done keeping volumes as the starting point
*/
Integer totalExport = recommendedPorts.size();
for (StorageVolume vol : volumes) {
Integer currExport = 0;
Integer hlu = Integer.parseInt(volumeToHLUMap.get(vol.getNativeId()));
try {
// volume could belong to different storage system; get specific api client;
HP3PARApi hp3parApi = hp3parUtil.getHP3PARDeviceFromNativeId(vol.getStorageSystemId(), driverRegistry);
/*
export for INDIVIDUAL HOST=exclusive
Some code is repeated with cluster for simplicity
*/
if (!host.startsWith("set:")) {
// try with recommended ports
for (StoragePort port : recommendedPorts) {
// volume and port belong to same storage system
String message = String.format(
"3PARDriver:exportVolumesToInitiators using recommendedPorts for "
+ "storage system %s, volume %s host %s hlu %s port %s",
port.getStorageSystemId(), vol.getNativeId(), host, hlu.toString(), port.getNativeId());
_log.info(message);
VlunResult vlunRes = hp3parApi.createVlun(vol.getNativeId(), hlu, host, port.getNativeId());
if (vlunRes != null && vlunRes.getStatus()) {
currExport++;
usedRecommendedPorts.setValue(true);
// update hlu obtained as lun from 3apr & add the selected port if required
volumeToHLUMap.put(vol.getNativeId(), vlunRes.getAssignedLun());
if (!selectedPorts.contains(port)) {
selectedPorts.add(port);
}
} else {
task.setStatus(DriverTask.TaskStatus.PARTIALLY_FAILED);
_log.warn("3PARDriver: Could not export " + message);
}
} // for recommended ports
// now try with available ports
for (StoragePort port : availablePorts) {
if (currExport == totalExport) {
task.setStatus(DriverTask.TaskStatus.READY);
break;
}
// Make sure this port is not used for earlier export
if (selectedPorts.contains(port)) {
continue;
}
// verify volume and port belong to same storage
if (!vol.getStorageSystemId().equalsIgnoreCase(port.getStorageSystemId())) {
continue;
}
String message = String.format(
"3PARDriver:exportVolumesToInitiators using availablePorts for "
+ "storage system %s, volume %s host %s hlu %s port %s",
port.getStorageSystemId(), vol.getNativeId(), host, hlu.toString(), port.getNativeId());
_log.info(message);
VlunResult vlunRes = hp3parApi.createVlun(vol.getNativeId(), hlu, host, port.getNativeId());
if (vlunRes != null && vlunRes.getStatus()) {
currExport++;
usedRecommendedPorts.setValue(false);
// update hlu obtained as lun from 3apr & add the selected port if required
volumeToHLUMap.put(vol.getNativeId(), vlunRes.getAssignedLun());
if (!selectedPorts.contains(port)) {
selectedPorts.add(port);
}
} else {
task.setStatus(DriverTask.TaskStatus.PARTIALLY_FAILED);
_log.warn("3PARDriver: Could not export " + message);
}
} // for available ports
} else {
/*
export for CLUSTER=shared
Some code is repeated with cluster for simplicity
Cluster export will be done as host-set in 3APR for entire cluster in one go.
Hence requests coming for rest of the individual host exports should gracefully exit
*/
String lockName = volumes.get(0).getStorageSystemId() + vol.getNativeId() + host;
if (driverLockManager.acquireLock(lockName, 10, TimeUnit.MINUTES)) {
_log.info("3PARDriver: Acquired lock {} to examine vlun creation", lockName);
/*
If this is the first request key gets created with export operation.
other requests will gracefully exit. key will be removed in unexport.
*/
String message = String.format(
"3PARDriver:exportVolumesToInitiators "
+ "storage system %s, volume %s Cluster %s hlu %s ",
vol.getStorageSystemId(), vol.getNativeId(), host, hlu.toString());
_log.info(message);
String exportPath = vol.getStorageSystemId() + vol.getNativeId() + host;
_log.info("3PARDriver:exportPath {} for registry entry", exportPath);
Map<String, List<String>> attributes = new HashMap<>();
List<String> expValue = new ArrayList<>();
List<String> lunValue = new ArrayList<>();
boolean doExport = true;
attributes = driverRegistry.getDriverAttributesForKey(HP3PARConstants.DRIVER_NAME,
exportPath);
if (attributes != null) {
expValue = attributes.get("EXPORT_PATH");
if (expValue != null && expValue.get(0).compareTo(exportPath) == 0) {
doExport = false;
// Already exported, make hlu, port details; gracefully exit
lunValue = attributes.get(vol.getNativeId());
volumeToHLUMap.put(vol.getNativeId(), lunValue.get(0));
HP3PARHostNameResult hostNameResult = get3parHostname(initiators, vol.getStorageSystemId(), driverRegistry);
HostMember hostRes = hp3parApi.getHostDetails(hostNameResult.getHostName());
// get storage array ports for this host ports
List<StoragePort> clusterStoragePorts = new ArrayList<>();
getClusterStoragePorts(hostRes, availablePorts, vol.getStorageSystemId(),
clusterStoragePorts);
for (StoragePort sp : clusterStoragePorts) {
// assign all these ports as selected ports
if (!selectedPorts.contains(sp)) {
selectedPorts.add(sp);
}
}
// go thru all slectedports.
// if anyone is not part of the recommendedPorts set usedRecommendedPorts to false
usedRecommendedPorts.setValue(true);
for (StoragePort sp : selectedPorts) {
if (!recommendedPorts.contains(sp)) {
usedRecommendedPorts.setValue(false);
break;
}
}
task.setStatus(DriverTask.TaskStatus.READY);
_log.info("3PARDriver: Already exported, exiting " + message);
}
}
if (doExport) {
_log.info("3PARDriver: exporting volume {} as exportPath {} is not present in registry", vol.getNativeId(), exportPath);
/*
for cluster use host set method, We cannot specify port;
determine the individual host ports used
*/
VlunResult vlunRes = hp3parApi.createVlun(vol.getNativeId(), hlu, host, null);
if (vlunRes != null && vlunRes.getStatus()) {
// update hlu obtained as lun from 3apr & add the selected port if required
volumeToHLUMap.put(vol.getNativeId(), vlunRes.getAssignedLun());
HP3PARHostNameResult hostNameResult = get3parHostname(initiators, vol.getStorageSystemId(), driverRegistry);
HostMember hostRes = hp3parApi.getHostDetails(hostNameResult.getHostName());
// get storage array ports for this host ports
List<StoragePort> clusterStoragePorts = new ArrayList<>();
getClusterStoragePorts(hostRes, availablePorts, vol.getStorageSystemId(),
clusterStoragePorts);
for (StoragePort sp : clusterStoragePorts) {
// assign all these ports as selected ports
if (!selectedPorts.contains(sp)) {
selectedPorts.add(sp);
}
}
usedRecommendedPorts.setValue(true);
for (StoragePort sp : selectedPorts) {
if (!recommendedPorts.contains(sp)) {
usedRecommendedPorts.setValue(false);
break;
}
}
// Everything is successful, Set as exported in registry
attributes = new HashMap<>();
expValue = new ArrayList<>();
lunValue = new ArrayList<>();
expValue.add(exportPath);
attributes.put("EXPORT_PATH", expValue);
lunValue.add(vlunRes.getAssignedLun());
attributes.put(vol.getNativeId(), lunValue);
attributes.put(vol.getNativeId(), lunValue);
driverRegistry.setDriverAttributesForKey(HP3PARConstants.DRIVER_NAME, exportPath,
attributes);
task.setMessage("Successful");
task.setStatus(DriverTask.TaskStatus.READY);
} else { // end createVlun
task.setStatus(DriverTask.TaskStatus.PARTIALLY_FAILED);
_log.warn("3PARDriver: Could not export " + message);
}
} // doExport
_log.info("3PARDriver: Releasing lock {} after examining vlun creation", lockName);
driverLockManager.releaseLock(lockName);
} else {
_log.error("3PARDriver:exportVolumesToInitiators error: could not acquire thread lock");
throw new HP3PARException(
"3PARDriver:exportVolumesToInitiators error: could not acquire thread lock");
}
} // end cluster export
} catch (Exception e) {
String msg = String.format("3PARDriver: Unable to export few volumes, error: %s", e);
_log.error(CompleteError.getStackTrace(e));
_log.error(msg);
task.setMessage(msg);
task.setStatus(DriverTask.TaskStatus.PARTIALLY_FAILED);
e.printStackTrace();
}
} // for each volume
_log.info("3PARDriver:exportVolumesToInitiators leave");
return task;
}
public DriverTask unexportVolumesFromInitiators(List<Initiator> initiators, List<StorageVolume> volumes,
DriverTask task, Registry driverRegistry, LockManager driverLockManager) {
_log.info("3PARDriver:unexportVolumesFromInitiators enter");
String host = null;
Boolean fullSuccess = true;
boolean gotLock = false;
String exportPath = null;
if (initiators.isEmpty() || volumes.isEmpty()) {
String msg = "3PARDriver:unexportVolumesFromInitiators error blank initiator and/or volumes";
_log.error(msg);
task.setMessage(msg);
task.setStatus(DriverTask.TaskStatus.FAILED);
return task;
}
HashMap<String, String> initiatorToHostMap = new HashMap<String, String>();
// unexport each volume
for (StorageVolume volume : volumes) {
try {
// get Api client for volume specific array
HP3PARApi hp3parApi = hp3parUtil.getHP3PARDeviceFromNativeId(volume.getStorageSystemId(),
driverRegistry);
VirtualLunsList vlunRes = hp3parApi.getVLunsByVolumeName(volume.getNativeId());
for (Initiator init : initiators) {
if(initiatorToHostMap.containsKey(init.getPort())){
host = initiatorToHostMap.get(init.getPort());
}
else{
ArrayList<Initiator> initList = new ArrayList<>();
initList.add(init);
HP3PARHostNameResult hostNameResult = get3parHostname(initList, volume.getStorageSystemId(), driverRegistry);
if (hostNameResult == null) {
fullSuccess = false;
String message = String.format(
"3PARDriver:unexportVolumesFromInitiators host not fond for " + "storage system %s, volume %s initiator %s",
volume.getStorageSystemId(), volume.getNativeId(), init.getPort());
_log.warn(message);
task.setMessage(message);
task.setStatus(DriverTask.TaskStatus.PARTIALLY_FAILED);
continue;
}
else {
host = hostNameResult.getHostName();
initiatorToHostMap.put(init.getPort(), host);
}
}
if (init.getInitiatorType().equals(Type.Host)) {
// get vlun and port details on this export
Integer lun = -1;
Position pos = null;
String portId = init.getPort();
portId = portId.replace(":", "");
Boolean found = false;
Integer vlunType = 0;
for (VirtualLun vLun:vlunRes.getMembers()) {
if (volume.getNativeId().compareTo(vLun.getVolumeName()) != 0 || (!vLun.isActive())
|| vLun.getRemoteName() == null || portId.compareToIgnoreCase(vLun.getRemoteName()) != 0 ||
(vLun.getType() != HP3PARConstants.vLunType.MATCHED_SET.getValue() &&
vLun.getType() != HP3PARConstants.vLunType.HOST.getValue()) ) {
continue;
}
lun = vLun.getLun();
pos = vLun.getPortPos();
vlunType = vLun.getType();
found = true;
break;
}
if (found) {
String posStr = null;
if (vlunType == HP3PARConstants.vLunType.MATCHED_SET.getValue()) {
//port details for matched set; null for host-sees
posStr = String.format("%s:%s:%s", pos.getNode(), pos.getSlot(), pos.getCardPort());
}
try{
hp3parApi.deleteVlun(volume.getNativeId(), lun.toString(), host, posStr);
}
catch(Exception e){
if(e.getMessage().contains(HP3PARConstants.VLUN_DOES_NOT_EXIST)){
_log.info("The VLUN(export info) does not exist on the 3PAR "
+ "array and hence this unexport will be treated as success");
}
else{
throw e;
}
}
}
if (!found) {
// port could be inactive, remove vlun template
for (VirtualLun vLun:vlunRes.getMembers()) {
if (volume.getNativeId().compareTo(vLun.getVolumeName()) != 0
|| vLun.getHostname() == null || host.compareToIgnoreCase(vLun.getHostname()) != 0 ||
(vLun.getType() != HP3PARConstants.vLunType.MATCHED_SET.getValue() &&
vLun.getType() != HP3PARConstants.vLunType.HOST.getValue()) ) {
continue;
}
lun = vLun.getLun();
pos = vLun.getPortPos();
vlunType = vLun.getType();
found = true;
if (found) {
String posStr = null;
if (vlunType == HP3PARConstants.vLunType.MATCHED_SET.getValue()) {
//port details for matched set; null for host-sees
posStr = String.format("%s:%s:%s", pos.getNode(), pos.getSlot(), pos.getCardPort());
}
_log.info("3PARDriver:unexportVolumesFromInitiators removing vlun template");
posStr = String.format("%s:%s:%s", pos.getNode(), pos.getSlot(), pos.getCardPort());
try{
hp3parApi.deleteVlun(volume.getNativeId(), lun.toString(), host, posStr);
}
catch(Exception e){
if(e.getMessage().contains(HP3PARConstants.VLUN_DOES_NOT_EXIST)){
_log.info("The VLUN(export info) does not exist on the 3PAR "
+ "array and hence this unexport will be treated as success");
}
else{
throw e;
}
}
} //found
} //end for all vlun templates
}
} else if (init.getInitiatorType().equals(Type.Cluster)) {
// cluster unexport
String clusterName = "set:" + initiators.get(0).getClusterName();
exportPath = volume.getStorageSystemId() + volume.getNativeId() + clusterName;
gotLock = false;
if (driverLockManager.acquireLock(exportPath, 10, TimeUnit.MINUTES)) {
gotLock = true;
Map<String, List<String>> attributes = new HashMap<>();
List<String> expValue = new ArrayList<>();
List<String> lunValue = new ArrayList<>();
boolean regPresent = false;
String message = String.format(
"3PARDriver:unexportVolumesFromInitiators for " + "storage system %s, volume %s Cluster %s",
volume.getStorageSystemId(), volume.getNativeId(), clusterName);
attributes = driverRegistry.getDriverAttributesForKey(HP3PARConstants.DRIVER_NAME, exportPath);
if (attributes != null) {
expValue = attributes.get("EXPORT_PATH");
if (expValue != null && expValue.get(0).compareTo(exportPath) == 0) {
lunValue = attributes.get(volume.getNativeId());
regPresent = true;
_log.info(message);
/*
* below operations are assumed to autonomic
*/
hp3parApi.deleteVlun(volume.getNativeId(), lunValue.get(0), clusterName, null);
driverRegistry.clearDriverAttributesForKey(HP3PARConstants.DRIVER_NAME, exportPath);
}
}
if (!regPresent) {
// gracefully exit, nothing to be done
_log.info("3PARDriver: Already unexported, exiting gracefully" + message);
}
driverLockManager.releaseLock(exportPath);
gotLock = false;
} else {// lock
_log.error("3PARDriver:unexportVolumesFromInitiators error: could not acquire thread lock");
throw new HP3PARException(
"3PARDriver:unexportVolumesFromInitiators error: could not acquire thread lock");
}
} // if cluster
} // for each initiator
} catch (Exception e) {
String msg = String.format("3PARDriver: Unable to unexport few volumes, error: %s", e);
_log.error(msg);
_log.error(CompleteError.getStackTrace(e));
task.setMessage(msg);
task.setStatus(DriverTask.TaskStatus.PARTIALLY_FAILED);
e.printStackTrace();
fullSuccess = false;
if (gotLock && (exportPath != null)) {
driverLockManager.releaseLock(exportPath);
}
}
} // for each volume
if (fullSuccess) {
task.setStatus(DriverTask.TaskStatus.READY);
}
_log.info("3PARDriver:unexportVolumesFromInitiatorss leave");
return task;
}
private void getClusterStoragePorts(HostMember hostRes, List<StoragePort> arrayPorts, String volStorageSystemId,
List<StoragePort> clusterPorts) {
for (StoragePort sp : arrayPorts) {
if (volStorageSystemId.compareToIgnoreCase(sp.getStorageSystemId()) != 0) {
continue;
}
String[] pos = sp.getNativeId().split(":");
for (FcPath fc:hostRes.getFCPaths()) {
if (fc.getPortPos() != null) {
if ((fc.getPortPos().getNode().toString().compareToIgnoreCase(pos[0]) == 0)
&& (fc.getPortPos().getSlot().toString().compareToIgnoreCase(pos[1]) == 0)
&& (fc.getPortPos().getCardPort().toString().compareToIgnoreCase(pos[2]) == 0)) {
// host connected array port
clusterPorts.add(sp);
}
} // porPos != null
} // for fc
}
}
private String doHostProcessing(List<Initiator> initiators, List<StorageVolume> volumes,
Registry driverRegistry, LockManager driverLockManager) {
String host = null; //will point host name in exclusive export and cluster name in shared export
String hostArray = null;
String clustArray = null;
// all volumes belong to same storage system
try {
// all initiators belong to same host
if (initiators.get(0).getInitiatorType().equals(Type.Host)) {
// Exclusive-Host export
// Some code is repeated with cluster for simplicity
HP3PARHostNameResult hostNameResult = get3parHostname(initiators, volumes.get(0).getStorageSystemId(), driverRegistry);
if (hostNameResult == null || hostNameResult.getAllInitiators() == false) {
// create a new host or add initiator to existing host
HP3PARApi hp3parApi = hp3parUtil.getHP3PARDeviceFromNativeId(volumes.get(0).getStorageSystemId(),
driverRegistry);
ArrayList<String> portIds = new ArrayList<>();
for (Initiator init : initiators) {
portIds.add(init.getPort());
}
Integer persona = getPersona(initiators.get(0).getHostOsType());
if (hostNameResult != null && hostNameResult.getHostName() != null) {
// if 3PAR registered host is found
host = hostNameResult.getHostName();
hp3parApi.updateHost(host, portIds);
} else {
// use CoprHD host name for new host
host = initiators.get(0).getHostName();
hp3parApi.createHost(host, portIds, persona);
}
} else {
host = hostNameResult.getHostName();
}
// Host available
} else if (initiators.get(0).getInitiatorType().equals(Type.Cluster)) {
// Shared-Cluster export
clustArray = initiators.get(0).getClusterName();
HP3PARApi hp3parApi = hp3parUtil.getHP3PARDeviceFromNativeId(volumes.get(0).getStorageSystemId(),
driverRegistry);
// Check if host exists, otherwise create
HP3PARHostNameResult hostNameResult = get3parHostname(initiators, volumes.get(0).getStorageSystemId(), driverRegistry);
if (hostNameResult == null || hostNameResult.getAllInitiators() == false) {
// create a new host or add initiator to existing host
ArrayList<String> portIds = new ArrayList<>();
for (Initiator init : initiators) {
portIds.add(init.getPort());
}
Integer persona = getPersona(initiators.get(0).getHostOsType());
if (hostNameResult != null && hostNameResult.getHostName() != null) {
// if 3PAR registered host is found
hostArray = hostNameResult.getHostName();
} else {
// use CoprHD host name
hostArray = initiators.get(0).getHostName();
}
hp3parApi.createHost(hostArray, portIds, persona);
} else {
hostArray = hostNameResult.getHostName();
}
// only one thread across all nodes should create cluster;
String lockName = volumes.get(0).getStorageSystemId() + clustArray;
if (driverLockManager.acquireLock(lockName, 10, TimeUnit.MINUTES)) {
// Check if cluster exists, otherwise create=>Cluster with +one host at a time
HostSetDetailsCommandResult hostsetRes = hp3parApi.getHostSetDetails(clustArray);
if (hostsetRes == null) {
hp3parApi.createHostSet(clustArray, initiators.get(0).getHostName());
} else {
// if this host is not part of the cluster add it
boolean present = false;
for (String setMember:hostsetRes.getSetmembers()) {
if (hostArray.compareTo(setMember) == 0) {
present = true;
break;
}
}
if (!present) {
// update cluster with this host
hp3parApi.updateHostSet(clustArray, hostArray);
}
}
// Cluster available
host = "set:" + clustArray;
driverLockManager.releaseLock(lockName);
} else {
_log.error("3PARDriver:doHostProcessing error: could not acquire thread lock to create cluster");
throw new HP3PARException(
"3PARDriver:doHostProcessing error: could not acquire thread lock to create cluster");
} //lock
} else {
_log.error("3PARDriver:exportVolumesToInitiators error: Host/Cluster type not supported");
throw new HP3PARException(
"3PARDriver:exportVolumesToInitiators error: Host/Cluster type not supported");
}
} catch (Exception e) {
String msg = String.format("3PARDriver: Unable to export, error: %s", e);
_log.error(msg);
_log.error(CompleteError.getStackTrace(e));
return null;
}
return host;
}
boolean hostHasAlliSCSIInitiators(List<Initiator> initiators, ArrayList<ISCSIPath> hostScPath) {
//get list of iqns in this host
ArrayList<String> hostIqns = new ArrayList<>();
for (ISCSIPath path:hostScPath) {
hostIqns.add(path.getName());
}
for (Initiator init:initiators) {
if (!hostIqns.contains(init.getPort())) {
//if any of the initiator is not part of the host
return false;
}
}
return true;
}
private boolean hostHasAllFcInitiators(List<Initiator> initiators, ArrayList<FcPath> hostFcPath) {
//get list of wwns in this host
ArrayList<String> hostWWNs = new ArrayList<>();
for (FcPath path:hostFcPath) {
hostWWNs.add(SanUtils.formatWWN(path.getWwn()));
}
for (Initiator init:initiators) {
if (!hostWWNs.contains(init.getPort())) {
//if any of the initiator is not part of the host
return false;
}
}
return true;
}
private HP3PARHostNameResult search3parHostName(List<Initiator> initiators, HostCommandResult hostRes) {
String hp3parHost = null;
HP3PARHostNameResult hp3parHostResult = new HP3PARHostNameResult();
// for each host in the result
for(HostMember hostMemb:hostRes.getMembers()) {
// for each host initiator sent
for (Initiator init : initiators) {
// Is initiator FC
if (Protocols.FC.toString().compareToIgnoreCase(init.getProtocol().toString()) == 0 ) {
// verify in all FC ports with host
for(FcPath fcPath: hostMemb.getFCPaths()) {
if (SanUtils.formatWWN(fcPath.getWwn()).compareToIgnoreCase(init.getPort()) == 0) {
hp3parHost = hostMemb.getName();
//Reference for residual initiator is present and there is no host name associated with this.
if (hp3parHost == null) {
continue;
}
hp3parHostResult.setHostName(hp3parHost);
// Confirm all initiators are present with this host
if (hostHasAllFcInitiators(initiators, hostMemb.getFCPaths())) {
_log.info("3PARDriver: get3parHostname FC initiator {} host {}", init.getPort(),
hp3parHost);
hp3parHostResult.setAllInitiators(true);
} else {
// same FC can not be part of any other host; exit
hp3parHostResult.setAllInitiators(false);
}
return hp3parHostResult;
}
}
} else if (Protocols.iSCSI.toString().compareToIgnoreCase(init.getProtocol().toString()) == 0 ){
// verify in all iSCSI ports with host
for (ISCSIPath scsiPath:hostMemb.getiSCSIPaths()) {
if (scsiPath.getName().compareToIgnoreCase(init.getPort()) == 0) {
hp3parHost = hostMemb.getName();
hp3parHostResult.setHostName(hp3parHost);
// Confirm all initiators are present with this host
if (hostHasAlliSCSIInitiators(initiators, hostMemb.getiSCSIPaths())) {
_log.info("3PARDriver: get3parHostname iSCSI initiator {} host {}", init.getPort(),
hp3parHost);
hp3parHostResult.setAllInitiators(true);
} else {
// same iSCSI can not be part of any other host
hp3parHostResult.setAllInitiators(false);
}
return hp3parHostResult;
}
}
} // if FC or iSCSI
} // each initiator
} // each host
return null;
}
private HP3PARHostNameResult get3parHostname(List<Initiator> initiators, String storageId,
Registry driverRegistry) throws Exception {
// Since query works this implementation can be changed
String hp3parHost = null;
_log.info("3PARDriver: get3parHostname enter");
try {
HP3PARApi hp3parApi = hp3parUtil.getHP3PARDeviceFromNativeId(storageId, driverRegistry);
HostCommandResult hostRes = hp3parApi.getAllHostDetails();
HP3PARHostNameResult hp3parHostResult = search3parHostName(initiators, hostRes);
_log.info("3PARDriver: get3parHostname leave");
return hp3parHostResult;
} catch (Exception e) {
_log.error("3PARDriver:get3parHostname could not get 3par registered host name");
_log.error(CompleteError.getStackTrace(e));
throw e;
}
}
private Integer getPersona(HostOsType hostType) {
Integer persona = 0;
// Supporting from lower OS versions;
switch (hostType) {
case Windows:
case Linux:
case SUNVCS:
persona = 1;
break;
case HPUX:
persona = 7;
break;
case Esx:
persona = 11;
break;
case AIX:
case AIXVIO:
persona = 8;
break;
// persona 3 is by experimentation, doc is not up-to-date
case No_OS:
case Other:
default:
persona = 3;
break;
}
return persona;
}
public HP3PARUtil getHp3parUtil() {
return hp3parUtil;
}
public void setHp3parUtil(HP3PARUtil hp3parUtil) {
this.hp3parUtil = hp3parUtil;
}
}