use of com.emc.storageos.vnxe.models.VNXeHostInitiator in project coprhd-controller by CoprHD.
the class VNXUnityUnManagedObjectDiscoverer method discoverUnmanagedExportMasks.
/**
* Create unmanaged export masks per host
*
* @param systemId
* @param hostVolumesMap
* host-- exportedvolume list
* @param apiClient
* @param dbClient
* @param partitionManager
* @throws Exception
*/
private void discoverUnmanagedExportMasks(URI systemId, Map<String, List<UnManagedVolume>> hostVolumesMap, VNXeApiClient apiClient, DbClient dbClient, PartitionManager partitionManager) throws Exception {
unManagedExportMasksToCreate = new ArrayList<UnManagedExportMask>();
unManagedExportMasksToUpdate = new ArrayList<UnManagedExportMask>();
List<UnManagedVolume> unManagedExportVolumesToUpdate = new ArrayList<UnManagedVolume>();
// In Unity, the volumes are exposed through all the storage ports.
// Get all the storage ports to be added as known ports in the unmanaged export mask
// If the host ports are FC, then add all FC storage ports to the mask
// else add all IP ports
StringSet knownFCStoragePortUris = new StringSet();
StringSet knownIPStoragePortUris = new StringSet();
List<StoragePort> matchedFCPorts = new ArrayList<StoragePort>();
URIQueryResultList storagePortURIs = new URIQueryResultList();
dbClient.queryByConstraint(ContainmentConstraint.Factory.getStorageDeviceStoragePortConstraint(systemId), storagePortURIs);
Iterator<URI> portsItr = storagePortURIs.iterator();
while (portsItr.hasNext()) {
URI storagePortURI = portsItr.next();
StoragePort port = dbClient.queryObject(StoragePort.class, storagePortURI);
if (TransportType.FC.toString().equals(port.getTransportType())) {
knownFCStoragePortUris.add(storagePortURI.toString());
matchedFCPorts.add(port);
} else if (TransportType.IP.toString().equals(port.getTransportType())) {
knownIPStoragePortUris.add(storagePortURI.toString());
}
}
for (Map.Entry<String, List<UnManagedVolume>> entry : hostVolumesMap.entrySet()) {
String hostId = entry.getKey();
List<UnManagedVolume> volumes = entry.getValue();
StringSet knownInitSet = new StringSet();
StringSet knownNetworkIdSet = new StringSet();
StringSet knownVolumeSet = new StringSet();
List<Initiator> matchedFCInitiators = new ArrayList<Initiator>();
VNXeHost host = apiClient.getHostById(hostId);
List<VNXeBase> fcInits = host.getFcHostInitiators();
List<VNXeBase> iScsiInits = host.getIscsiHostInitiators();
boolean isVplexHost = false;
boolean isRPHost = false;
Set<URI> hostURIs = new HashSet<>();
if (fcInits != null && !fcInits.isEmpty()) {
for (VNXeBase init : fcInits) {
VNXeHostInitiator initiator = apiClient.getHostInitiator(init.getId());
String portwwn = initiator.getPortWWN();
if (portwwn == null || portwwn.isEmpty()) {
continue;
}
Initiator knownInitiator = NetworkUtil.getInitiator(portwwn, dbClient);
if (knownInitiator != null) {
knownInitSet.add(knownInitiator.getId().toString());
knownNetworkIdSet.add(portwwn);
matchedFCInitiators.add(knownInitiator);
URI hostURI = knownInitiator.getHost();
if (!NullColumnValueGetter.isNullURI(hostURI) && URIUtil.isType(hostURI, Host.class)) {
hostURIs.add(hostURI);
}
} else {
knownInitiator = new Initiator();
knownInitiator.setInitiatorPort(portwwn);
}
if (!isVplexHost && VPlexControllerUtils.isVplexInitiator(knownInitiator, dbClient)) {
isVplexHost = true;
}
}
}
if (!matchedFCInitiators.isEmpty() && ExportUtils.checkIfInitiatorsForRP(matchedFCInitiators)) {
log.info("host {} contains RP initiators, " + "so this mask contains RP protected volumes", host.getName());
isRPHost = true;
}
if (iScsiInits != null && !iScsiInits.isEmpty()) {
for (VNXeBase init : iScsiInits) {
VNXeHostInitiator initiator = apiClient.getHostInitiator(init.getId());
String portwwn = initiator.getInitiatorId();
if (portwwn == null || portwwn.isEmpty()) {
continue;
}
Initiator knownInitiator = NetworkUtil.getInitiator(portwwn, dbClient);
if (knownInitiator != null) {
knownInitSet.add(knownInitiator.getId().toString());
knownNetworkIdSet.add(portwwn);
URI hostURI = knownInitiator.getHost();
if (!NullColumnValueGetter.isNullURI(hostURI) && URIUtil.isType(hostURI, Host.class)) {
hostURIs.add(hostURI);
}
}
}
}
if (knownNetworkIdSet.isEmpty()) {
log.info(String.format("The host %s does not have any known initiators", hostId));
continue;
}
if (hostURIs.size() > 1) {
log.warn(String.format("Skip export on host %s as the initiators on the host belong to more than one hosts in DB %s", hostId, Joiner.on(",").join(hostURIs)));
continue;
}
String firstNetworkId = knownNetworkIdSet.iterator().next();
UnManagedExportMask mask = getUnManagedExportMask(firstNetworkId, dbClient, systemId);
mask.setStorageSystemUri(systemId);
// set the host name as the mask name
mask.setMaskName(host.getName());
allCurrentUnManagedExportMaskUris.add(mask.getId());
for (UnManagedVolume hostUnManagedVol : volumes) {
hostUnManagedVol.getInitiatorNetworkIds().addAll(knownNetworkIdSet);
hostUnManagedVol.getInitiatorUris().addAll(knownInitSet);
hostUnManagedVol.getUnmanagedExportMasks().add(mask.getId().toString());
if (isVplexHost) {
log.info("marking unmanaged unity volume {} as a VPLEX backend volume", hostUnManagedVol.getLabel());
hostUnManagedVol.putVolumeCharacterstics(SupportedVolumeCharacterstics.IS_VPLEX_BACKEND_VOLUME.toString(), Boolean.TRUE.toString());
}
if (isRPHost) {
log.info("unmanaged volume {} is an RP volume", hostUnManagedVol.getLabel());
hostUnManagedVol.putVolumeCharacterstics(SupportedVolumeCharacterstics.IS_RECOVERPOINT_ENABLED.toString(), Boolean.TRUE.toString());
} else {
log.info("unmanaged volume {} is exported to something other than RP. Marking IS_NONRP_EXPORTED.", hostUnManagedVol.forDisplay());
hostUnManagedVol.putVolumeCharacterstics(SupportedVolumeCharacterstics.IS_NONRP_EXPORTED.toString(), Boolean.TRUE.toString());
}
mask.getUnmanagedVolumeUris().add(hostUnManagedVol.getId().toString());
// update mask to HLU information
StringSet nativeId = hostUnManagedVol.getVolumeInformation().get(SupportedVolumeInformation.NATIVE_ID.name());
String nativeGuid = hostUnManagedVol.getNativeGuid();
String lunId = (nativeId != null && nativeId.iterator().hasNext()) ? nativeId.iterator().next() : nativeGuid.substring(nativeGuid.lastIndexOf(Constants.PLUS) + 1);
String idCharSequence = HostLunRequests.ID_SEQUENCE_LUN;
if (Boolean.valueOf(hostUnManagedVol.getVolumeCharacterstics().get(SupportedVolumeCharacterstics.IS_SNAP_SHOT.name()))) {
idCharSequence = HostLunRequests.ID_SEQUENCE_SNAP;
Snap snap = apiClient.getSnapshot(lunId);
// get snap's parent id
lunId = snap.getLun().getId();
}
HostLun hostLun = apiClient.getHostLun(lunId, hostId, idCharSequence);
if (hostLun != null) {
String hostHlu = host.getName() + "=" + hostLun.getHlu();
StringSet existingHostHlu = hostUnManagedVol.getVolumeInformation().get(SupportedVolumeInformation.HLU_TO_EXPORT_MASK_NAME_MAP.name());
if (existingHostHlu != null) {
existingHostHlu.add(hostHlu);
} else {
hostUnManagedVol.getVolumeInformation().put(SupportedVolumeInformation.HLU_TO_EXPORT_MASK_NAME_MAP.name(), hostHlu);
}
}
unManagedExportVolumesToUpdate.add(hostUnManagedVol);
}
mask.replaceNewWithOldResources(knownInitSet, knownNetworkIdSet, knownVolumeSet, !matchedFCInitiators.isEmpty() ? knownFCStoragePortUris : knownIPStoragePortUris);
updateZoningMap(mask, matchedFCInitiators, matchedFCPorts);
}
if (!unManagedExportMasksToCreate.isEmpty()) {
partitionManager.insertInBatches(unManagedExportMasksToCreate, Constants.DEFAULT_PARTITION_SIZE, dbClient, UNMANAGED_EXPORT_MASK);
unManagedExportMasksToCreate.clear();
}
if (!unManagedExportMasksToUpdate.isEmpty()) {
partitionManager.updateInBatches(unManagedExportMasksToUpdate, Constants.DEFAULT_PARTITION_SIZE, dbClient, UNMANAGED_EXPORT_MASK);
unManagedExportMasksToUpdate.clear();
}
if (!unManagedExportVolumesToUpdate.isEmpty()) {
partitionManager.updateAndReIndexInBatches(unManagedExportVolumesToUpdate, Constants.DEFAULT_PARTITION_SIZE, dbClient, UNMANAGED_VOLUME);
unManagedExportVolumesToUpdate.clear();
}
DiscoveryUtils.markInActiveUnManagedExportMask(systemId, allCurrentUnManagedExportMaskUris, dbClient, partitionManager);
}
use of com.emc.storageos.vnxe.models.VNXeHostInitiator in project coprhd-controller by CoprHD.
the class VNXeApiClient method prepareHostsForExport.
/**
* given host name and initiators, find/create hosts/initiators in the
*
* @param hostInitiators
* @return
*/
public VNXeBase prepareHostsForExport(Collection<VNXeHostInitiator> hostInitiators) throws VNXeException {
String hostId = null;
Set<VNXeHostInitiator> notExistingInits = new HashSet<VNXeHostInitiator>();
Set<VNXeHostInitiator> existingNoHostInits = new HashSet<VNXeHostInitiator>();
String hostOsType = null;
String hostName = null;
for (VNXeHostInitiator init : hostInitiators) {
VNXeHostInitiator existingInit = getInitiatorByWWN(init.getInitiatorId());
if (existingInit != null && existingInit.getParentHost() != null) {
if (hostId == null) {
hostId = existingInit.getParentHost().getId();
} else if (!hostId.equals(existingInit.getParentHost().getId())) {
_logger.error("Initiators belong to different hosts");
throw VNXeException.exceptions.vnxeCommandFailed("Initiators belong to different hosts");
}
} else if (existingInit != null) {
existingNoHostInits.add(existingInit);
} else {
notExistingInits.add(init);
}
if (hostOsType == null) {
hostOsType = init.getHostOsType();
}
if (hostName == null) {
hostName = init.getName();
}
}
if (hostId == null) {
// create host and hostInitiator
HostListRequest hostReq = new HostListRequest(_khClient);
HostCreateParam hostCreateParm = new HostCreateParam();
hostCreateParm.setName(hostName);
hostCreateParm.setType(HostTypeEnum.HOSTMANUAL.getValue());
if (isUnityClient() && hostOsType != null) {
hostCreateParm.setOsType(hostOsType);
}
VNXeCommandResult result = hostReq.createHost(hostCreateParm);
hostId = result.getId();
}
for (VNXeHostInitiator newInit : notExistingInits) {
HostInitiatorCreateParam initCreateParam = new HostInitiatorCreateParam();
VNXeBase host = new VNXeBase(hostId);
initCreateParam.setHost(host);
if (newInit.getType() == HostInitiatorTypeEnum.INITIATOR_TYPE_ISCSI) {
initCreateParam.setInitiatorType(HostInitiatorTypeEnum.INITIATOR_TYPE_ISCSI.getValue());
initCreateParam.setInitiatorWWNorIqn(newInit.getChapUserName());
initCreateParam.setChapUser(newInit.getChapUserName());
} else {
initCreateParam.setInitiatorType(HostInitiatorTypeEnum.INITIATOR_TYPE_FC.getValue());
initCreateParam.setInitiatorWWNorIqn(newInit.getInitiatorId());
}
HostInitiatorRequest req = new HostInitiatorRequest(_khClient);
try {
req.createHostInitiator(initCreateParam);
} catch (VNXeException e) {
// For ESX hosts, even if we could not get the initiators when we query them, when we try to create the host
// initiator with the created host, it would throw error, saying the initiator exists. ignore the error.
String message = e.getMessage();
if (message != null && message.contains(VNXeConstants.INITIATOR_EXISITNG)) {
_logger.info("The initiator exists. Ignore the error.");
} else {
throw e;
}
}
}
for (VNXeHostInitiator exitInit : existingNoHostInits) {
setInitiatorHost(exitInit.getId(), hostId);
}
return new VNXeBase(hostId);
}
use of com.emc.storageos.vnxe.models.VNXeHostInitiator in project coprhd-controller by CoprHD.
the class VNXeExportMaskInitiatorsValidator method validate.
/**
* Get list of initiators associated with the host.
* If there are unknown initiators on the host, fail the validation
*/
@Override
public boolean validate() throws Exception {
log.info("Initiating initiator validation of VNXe ExportMask: " + getId());
DbClient dbClient = getDbClient();
VNXeApiClient apiClient = getApiClient();
ExportMask exportMask = getExportMask();
try {
// Don't validate against backing masks or RP
if (ExportMaskUtils.isBackendExportMask(getDbClient(), exportMask)) {
log.info("validation against backing mask for VPLEX or RP is disabled.");
return true;
}
// all initiators of VNXe host should be on single ViPR host, or unknown to ViPR
String vnxeHostId = getHostId();
if (vnxeHostId == null) {
return true;
}
List<VNXeHostInitiator> initiatorList = apiClient.getInitiatorsByHostId(vnxeHostId);
URI hostId = null;
if (initiatorList != null) {
for (VNXeHostInitiator initiator : initiatorList) {
String portWWN = null;
if (HostInitiatorTypeEnum.INITIATOR_TYPE_ISCSI.equals(initiator.getType())) {
portWWN = initiator.getInitiatorId();
} else {
portWWN = initiator.getPortWWN();
}
Initiator viprInitiator = NetworkUtil.findInitiatorInDB(portWWN, dbClient);
if (viprInitiator != null) {
if (NullColumnValueGetter.isNullURI(hostId)) {
hostId = viprInitiator.getHost();
} else if (!hostId.equals(viprInitiator.getHost())) {
log.info("Initiator {} belongs to different host", portWWN);
setRemediation(misMatchInitiatorRemediation);
getLogger().logDiff(exportMask.getId().toString(), "initiators", ValidatorLogger.NO_MATCHING_ENTRY, portWWN);
break;
}
} else {
// initiator not found in ViPR
log.info("Unknown initiator found: {}", portWWN);
setRemediation(unknownInitiatorRemediation);
getLogger().logDiff(exportMask.getId().toString(), "initiators", ValidatorLogger.NO_MATCHING_ENTRY, portWWN);
break;
}
}
}
} catch (Exception ex) {
log.error("Unexpected exception validating ExportMask initiators: " + ex.getMessage(), ex);
if (getConfig().isValidationEnabled()) {
throw DeviceControllerException.exceptions.unexpectedCondition("Unexpected exception validating ExportMask initiators: " + ex.getMessage());
}
}
checkForErrors();
log.info("Completed initiator validation of VNXe ExportMask: " + getId());
return true;
}
use of com.emc.storageos.vnxe.models.VNXeHostInitiator in project coprhd-controller by CoprHD.
the class VNXeExportOperations method removeInitiators.
@Override
public void removeInitiators(StorageSystem storage, URI exportMask, List<URI> volumeURIList, List<Initiator> initiators, List<URI> targets, TaskCompleter taskCompleter) throws DeviceControllerException {
_logger.info("{} removeInitiators START...", storage.getSerialNumber());
ExportMask mask = _dbClient.queryObject(ExportMask.class, exportMask);
if (mask == null || mask.getInactive()) {
_logger.error(String.format("The exportMask %s is invalid.", exportMask));
throw DeviceControllerException.exceptions.invalidObjectNull();
}
boolean isRollback = WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId());
if (isRollback) {
List<Initiator> addedInitiators = new ArrayList<Initiator>();
// Get the context from the task completer, in case this is a rollback.
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
if (context != null && context.getOperations() != null) {
_logger.info("Handling removeInitiators as a result of rollback");
ListIterator li = context.getOperations().listIterator(context.getOperations().size());
while (li.hasPrevious()) {
ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
if (operation != null && VNXeExportOperationContext.OPERATION_ADD_INITIATORS_TO_HOST.equals(operation.getOperation())) {
addedInitiators = (List<Initiator>) operation.getArgs().get(0);
_logger.info("Removing initiators {} as part of rollback", Joiner.on(',').join(addedInitiators));
}
}
}
// Update the initiators in the task completer such that we update the export mask/group correctly
for (Initiator initiator : initiators) {
if (addedInitiators == null || !addedInitiators.contains(initiator)) {
((ExportMaskRemoveInitiatorCompleter) taskCompleter).removeInitiator(initiator.getId());
}
}
initiators = addedInitiators;
if (initiators == null || initiators.isEmpty()) {
_logger.info("There was no context found for add initiator. So there is nothing to rollback.");
taskCompleter.ready(_dbClient);
return;
}
}
StringSet initiatorsInMask = mask.getInitiators();
List<Initiator> initiatorToBeRemoved = new ArrayList<>();
for (Initiator initiator : initiators) {
if (initiatorsInMask.contains(initiator.getId().toString())) {
initiatorToBeRemoved.add(initiator);
}
}
try {
VNXeApiClient apiClient = getVnxeClient(storage);
List<Initiator> allInitiators = ExportUtils.getExportMaskInitiators(exportMask, _dbClient);
String vnxeHostId = getHostIdFromInitiators(allInitiators, apiClient);
if (vnxeHostId != null) {
List<VNXeHostInitiator> vnxeInitiators = apiClient.getInitiatorsByHostId(vnxeHostId);
// initiators is a subset of allInitiators
Map<Initiator, VNXeHostInitiator> vnxeInitiatorsToBeRemoved = prepareInitiators(initiatorToBeRemoved);
Set<String> initiatorIds = new HashSet<String>();
for (VNXeHostInitiator vnxeInit : vnxeInitiators) {
initiatorIds.add(vnxeInit.getInitiatorId());
}
Set<String> initiatorsToBeRemoved = new HashSet<String>();
for (VNXeHostInitiator vnxeInit : vnxeInitiatorsToBeRemoved.values()) {
String initiatorId = vnxeInit.getId();
if (initiatorIds.remove(initiatorId)) {
initiatorsToBeRemoved.add(initiatorId);
}
}
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(storage);
ctx.setExportMask(mask);
ctx.setBlockObjects(volumeURIList, _dbClient);
// Allow exceptions to be thrown when not rolling back
ctx.setAllowExceptions(!isRollback);
AbstractVNXeValidator removeInitiatorsValidator = (AbstractVNXeValidator) validator.removeInitiators(ctx);
removeInitiatorsValidator.setHostId(vnxeHostId);
removeInitiatorsValidator.validate();
// 3. shared initiators, but all export masks have same set of initiators
if (!isRollback) {
boolean hasSharedInitiator = false;
for (Initiator initiator : initiatorToBeRemoved) {
if (ExportUtils.isInitiatorSharedByMasks(_dbClient, mask, initiator.getId())) {
hasSharedInitiator = true;
break;
}
}
if (hasSharedInitiator) {
validateAllMasks(_dbClient, mask, apiClient, vnxeHostId);
}
}
}
List<String> initiatorIdList = new ArrayList<>();
for (Initiator initiator : initiatorToBeRemoved) {
_logger.info("Processing initiator {}", initiator.getLabel());
if (vnxeHostId != null) {
String initiatorId = initiator.getInitiatorPort();
if (Protocol.FC.name().equals(initiator.getProtocol())) {
initiatorId = initiator.getInitiatorNode() + ":" + initiatorId;
}
initiatorIdList.add(initiatorId);
}
mask.removeFromExistingInitiators(initiator);
mask.removeFromUserCreatedInitiators(initiator);
}
if (!initiatorIdList.isEmpty()) {
apiClient.deleteInitiators(initiatorIdList);
}
_dbClient.updateObject(mask);
taskCompleter.ready(_dbClient);
} catch (Exception e) {
_logger.error("Problem in removeInitiators: ", e);
ServiceError serviceError = DeviceControllerErrors.vnxe.jobFailed("removeInitiator", e.getMessage());
taskCompleter.error(_dbClient, serviceError);
}
_logger.info("{} removeInitiators END...", storage.getSerialNumber());
}
use of com.emc.storageos.vnxe.models.VNXeHostInitiator in project coprhd-controller by CoprHD.
the class VNXeExportOperations method deleteExportMask.
@Override
public void deleteExportMask(StorageSystem storage, URI exportMaskUri, List<URI> volumeURIList, List<URI> targetURIList, List<Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException {
_logger.info("{} deleteExportMask START...", storage.getSerialNumber());
boolean removeLastInitiator = false;
List<URI> volumesToBeUnmapped = new ArrayList<URI>();
try {
_logger.info("Export mask id: {}", exportMaskUri);
if (volumeURIList != null) {
_logger.info("deleteExportMask: volumes: {}", Joiner.on(',').join(volumeURIList));
}
if (targetURIList != null) {
_logger.info("deleteExportMask: assignments: {}", Joiner.on(',').join(targetURIList));
}
if (initiatorList != null) {
if (!initiatorList.isEmpty()) {
removeLastInitiator = true;
_logger.info("deleteExportMask: initiators: {}", Joiner.on(',').join(initiatorList));
}
}
// Get the context from the task completer, in case this is a rollback.
boolean isRollback = WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId());
if (isRollback) {
List<URI> addedVolumes = new ArrayList<URI>();
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
if (context != null && context.getOperations() != null) {
_logger.info("Handling deleteExportMask as a result of rollback");
ListIterator li = context.getOperations().listIterator(context.getOperations().size());
while (li.hasPrevious()) {
ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
if (operation != null && VNXeExportOperationContext.OPERATION_ADD_VOLUMES_TO_HOST_EXPORT.equals(operation.getOperation())) {
addedVolumes = (List<URI>) operation.getArgs().get(0);
_logger.info("Removing volumes {} as part of rollback", Joiner.on(',').join(addedVolumes));
}
}
}
volumesToBeUnmapped = addedVolumes;
if (volumesToBeUnmapped == null || volumesToBeUnmapped.isEmpty()) {
_logger.info("There was no context found for add volumes. So there is nothing to rollback.");
taskCompleter.ready(_dbClient);
return;
}
} else {
volumesToBeUnmapped = volumeURIList;
}
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskUri);
if (exportMask == null || exportMask.getInactive()) {
throw new DeviceControllerException("Invalid ExportMask URI: " + exportMaskUri);
}
if (initiatorList.isEmpty()) {
initiatorList = ExportUtils.getExportMaskInitiators(exportMask, _dbClient);
}
VNXeApiClient apiClient = getVnxeClient(storage);
String hostId = getHostIdFromInitiators(initiatorList, apiClient);
Set<String> allExportedVolumes = new HashSet<>();
if (hostId != null) {
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(storage);
ctx.setExportMask(exportMask);
ctx.setBlockObjects(volumeURIList, _dbClient);
ctx.setInitiators(initiatorList);
// Allow exceptions to be thrown when not rolling back
ctx.setAllowExceptions(!isRollback);
AbstractVNXeValidator deleteMaskValidator = (AbstractVNXeValidator) validator.exportMaskDelete(ctx);
deleteMaskValidator.setHostId(hostId);
deleteMaskValidator.validate();
if (removeLastInitiator) {
ctx = new ExportMaskValidationContext();
ctx.setStorage(storage);
ctx.setExportMask(exportMask);
ctx.setBlockObjects(volumeURIList, _dbClient);
ctx.setAllowExceptions(!isRollback);
AbstractVNXeValidator removeInitiatorsValidator = (AbstractVNXeValidator) validator.removeInitiators(ctx);
removeInitiatorsValidator.setHostId(hostId);
removeInitiatorsValidator.validate();
boolean hasSharedInitiator = false;
for (String strUri : exportMask.getInitiators()) {
if (ExportUtils.isInitiatorSharedByMasks(_dbClient, exportMask, URI.create(strUri))) {
hasSharedInitiator = true;
_logger.info("Initiators are used by multiple export masks");
break;
}
}
if (hasSharedInitiator) {
// if any initiator is shared, all initiators have to be shared, and each mask should have same set of initiators
// Otherwise, removing initiator will not be allowed, user can delete individual export mask
Collection<ExportMask> masksWithSharedInitiators = validateAllMasks(_dbClient, exportMask, apiClient, hostId);
_logger.info("Masks use the same initiators {}", Joiner.on(", ").join(Collections2.transform(masksWithSharedInitiators, CommonTransformerFunctions.fctnDataObjectToForDisplay())));
// need to unexport all volumes of all export masks
// except shared export co-exists with exclusive export, don't touch exclusive export
// in case of multiple shared exports (e.g., with different projects), all exported LUNs will be unmapped, regardless exclusive export
String exportType = ExportMaskUtils.getExportType(_dbClient, exportMask);
if (ExportGroupType.Cluster.name().equals(exportType)) {
Iterator<ExportMask> maskIter = masksWithSharedInitiators.iterator();
while (maskIter.hasNext()) {
ExportMask mask = maskIter.next();
if (!ExportGroupType.Cluster.name().equals(ExportMaskUtils.getExportType(_dbClient, mask))) {
_logger.info("Ignore exclusive export {}", mask.getMaskName());
maskIter.remove();
}
}
}
volumesToBeUnmapped.addAll(getExportedVolumes(_dbClient, storage.getId(), masksWithSharedInitiators));
}
}
allExportedVolumes = ExportUtils.getAllLUNsForHost(_dbClient, exportMask);
}
String opId = taskCompleter.getOpId();
Set<String> processedCGs = new HashSet<String>();
for (URI volUri : volumesToBeUnmapped) {
if (hostId != null) {
BlockObject blockObject = BlockObject.fetch(_dbClient, volUri);
String nativeId = blockObject.getNativeId();
String cgName = VNXeUtils.getBlockObjectCGName(blockObject, _dbClient);
if (cgName != null && !processedCGs.contains(cgName)) {
processedCGs.add(cgName);
VNXeUtils.getCGLock(workflowService, storage, cgName, opId);
}
if (URIUtil.isType(volUri, Volume.class)) {
apiClient.unexportLun(hostId, nativeId);
} else if (URIUtil.isType(volUri, BlockSnapshot.class)) {
if (BlockObject.checkForRP(_dbClient, volUri)) {
_logger.info(String.format("BlockObject %s is a RecoverPoint bookmark. Un-exporting associated lun %s instead of snap.", volUri, nativeId));
apiClient.unexportLun(hostId, nativeId);
} else {
apiClient.unexportSnap(hostId, nativeId);
setSnapWWN(apiClient, blockObject, nativeId);
}
}
}
// update the exportMask object
exportMask.removeVolume(volUri);
}
// check if there are LUNs on array
// initiator will not be able to removed if there are LUNs belongs to other masks (if initiator is shared), or unknown to ViPR
Set<String> lunIds = new HashSet<>();
if (hostId != null) {
lunIds = apiClient.getHostLUNIds(hostId);
_logger.info("Mapped resources {}", Joiner.on(", ").join(lunIds));
}
boolean hasLUN = lunIds.isEmpty() ? false : true;
lunIds.removeAll(allExportedVolumes);
boolean hasUnknownLUN = lunIds.isEmpty() ? false : true;
_logger.info("Export mask deletion - hasLUN {}, hasUnknownLUN {}", hasLUN, hasUnknownLUN);
for (Initiator initiator : initiatorList) {
_logger.info("Processing initiator {}", initiator.getLabel());
if (hostId != null && (!hasLUN || (!hasUnknownLUN && !ExportUtils.isInitiatorSharedByMasks(_dbClient, exportMask, initiator.getId())))) {
String initiatorId = initiator.getInitiatorPort();
if (Protocol.FC.name().equals(initiator.getProtocol())) {
initiatorId = initiator.getInitiatorNode() + ":" + initiatorId;
}
try {
if (hasLUN) {
// move and delete initiator
apiClient.deleteInitiators(new ArrayList<String>(Arrays.asList(initiatorId)));
} else {
apiClient.deleteInitiator(initiatorId);
}
} catch (VNXeException e) {
_logger.warn("Error on deleting initiator: {}", e.getMessage());
}
}
exportMask.removeFromExistingInitiators(initiator);
exportMask.removeFromUserCreatedInitiators(initiator);
}
_dbClient.updateObject(exportMask);
if (hostId != null) {
List<VNXeHostInitiator> vnxeInitiators = apiClient.getInitiatorsByHostId(hostId);
if (vnxeInitiators.isEmpty()) {
Set<String> vnxeLUNIds = apiClient.getHostLUNIds(hostId);
if ((vnxeLUNIds.isEmpty())) {
try {
apiClient.deleteHost(hostId);
} catch (VNXeException e) {
_logger.warn("Error on deleting host: {}", e.getMessage());
}
}
}
}
List<ExportGroup> exportGroups = ExportMaskUtils.getExportGroups(_dbClient, exportMask);
if (exportGroups != null) {
// Remove the mask references in the export group
for (ExportGroup exportGroup : exportGroups) {
// Remove this mask from the export group
exportGroup.removeExportMask(exportMask.getId().toString());
}
// Update all of the export groups in the DB
_dbClient.updateObject(exportGroups);
}
taskCompleter.ready(_dbClient);
} catch (Exception e) {
_logger.error("Unexpected error: deleteExportMask failed.", e);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("deleteExportMask", e.getMessage());
taskCompleter.error(_dbClient, error);
}
_logger.info("{} deleteExportMask END...", storage.getSerialNumber());
}
Aggregations