use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskCreateCompleter in project coprhd-controller by CoprHD.
the class VPlexVnxMaskingOrchestrator method createOrAddVolumesToExportMask.
@Override
public void createOrAddVolumesToExportMask(URI arrayURI, URI exportGroupURI, URI exportMaskURI, Map<URI, Integer> volumeMap, List<URI> initiatorURIs2, TaskCompleter completer, String stepId) {
try {
StorageSystem array = _dbClient.queryObject(StorageSystem.class, arrayURI);
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
WorkflowStepCompleter.stepExecuting(stepId);
// If the exportMask isn't found, or has been deleted, fail, ask user to retry.
if (exportMask == null || exportMask.getInactive()) {
_log.info(String.format("ExportMask %s deleted or inactive, failing", exportMaskURI));
ServiceError svcerr = VPlexApiException.errors.createBackendExportMaskDeleted(exportMaskURI.toString(), arrayURI.toString());
WorkflowStepCompleter.stepFailed(stepId, svcerr);
return;
}
// Protect concurrent operations by locking {host, array} dupple.
// Lock will be released when workflow step completes.
List<String> lockKeys = ControllerLockingUtil.getHostStorageLockKeys(_dbClient, ExportGroupType.Host, StringSetUtil.stringSetToUriList(exportMask.getInitiators()), arrayURI);
getWorkflowService().acquireWorkflowStepLocks(stepId, lockKeys, LockTimeoutValue.get(LockType.VPLEX_BACKEND_EXPORT));
// Fetch the Initiators
List<URI> initiatorURIs = new ArrayList<URI>();
List<Initiator> initiators = new ArrayList<Initiator>();
for (String initiatorId : exportMask.getInitiators()) {
Initiator initiator = _dbClient.queryObject(Initiator.class, URI.create(initiatorId));
if (initiator != null) {
initiators.add(initiator);
initiatorURIs.add(initiator.getId());
}
}
// We do not refresh here, as the VNXExportOperations code will throw an exception
// if the StorageGroup was not found.
BlockStorageDevice device = _blockController.getDevice(array.getSystemType());
if (!exportMask.hasAnyVolumes() && exportMask.getCreatedBySystem()) {
// We are creating this ExportMask on the hardware! (Maybe not the first time though...)
// Fetch the targets
List<URI> targets = new ArrayList<URI>();
for (String targetId : exportMask.getStoragePorts()) {
targets.add(URI.create(targetId));
}
// up and fail. An empty String will suffice as having no nativeId.
if (exportMask.getNativeId() != null) {
exportMask.setNativeId("");
_dbClient.updateAndReindexObject(exportMask);
}
// The default completer passed in is for add volume, create correct one
completer = new ExportMaskCreateCompleter(exportGroupURI, exportMaskURI, initiatorURIs, volumeMap, stepId);
device.doExportCreate(array, exportMask, volumeMap, initiators, targets, completer);
} else {
device.doExportAddVolumes(array, exportMask, initiators, volumeMap, completer);
}
} catch (Exception ex) {
_log.error("Failed to create or add volumes to export mask for vnx: ", ex);
VPlexApiException vplexex = DeviceControllerExceptions.vplex.addStepsForCreateVolumesFailed(ex);
WorkflowStepCompleter.stepFailed(stepId, vplexex);
}
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskCreateCompleter in project coprhd-controller by CoprHD.
the class VPlexXIVMaskingOrchestrator method createOrAddVolumesToExportMask.
/*
* (non-Javadoc)
*
* @see com.emc.storageos.volumecontroller.impl.block.
* VplexBackEndMaskingOrchestrator#createOrAddVolumesToExportMask(java.net.URI, java.net.URI,
* java.net.URI, java.util.Map, com.emc.storageos.volumecontroller.TaskCompleter, java.lang.String)
*/
@Override
public void createOrAddVolumesToExportMask(URI arrayURI, URI exportGroupURI, URI exportMaskURI, Map<URI, Integer> volumeMap, List<URI> initiatorURIs2, TaskCompleter completer, String stepId) {
try {
WorkflowStepCompleter.stepExecuting(stepId);
StorageSystem array = _dbClient.queryObject(StorageSystem.class, arrayURI);
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
// If the exportMask isn't found, or has been deleted, fail, ask user to retry.
if (exportMask == null || exportMask.getInactive()) {
_log.info(String.format("ExportMask %s deleted or inactive, failing", exportMaskURI));
ServiceError svcerr = VPlexApiException.errors.createBackendExportMaskDeleted(exportMaskURI.toString(), arrayURI.toString());
WorkflowStepCompleter.stepFailed(stepId, svcerr);
return;
}
// Protect concurrent operations by locking {host, array} dupple.
// Lock will be released when workflow step completes.
List<String> lockKeys = ControllerLockingUtil.getHostStorageLockKeys(_dbClient, ExportGroupType.Host, StringSetUtil.stringSetToUriList(exportMask.getInitiators()), arrayURI);
getWorkflowService().acquireWorkflowStepLocks(stepId, lockKeys, LockTimeoutValue.get(LockType.VPLEX_BACKEND_EXPORT));
// Refresh the ExportMask
BlockStorageDevice device = _blockController.getDevice(array.getSystemType());
if (exportMask.getNativeId() != null) {
exportMask = refreshExportMask(array, device, exportMask);
}
// We are creating this ExportMask on the hardware! (Maybe not the first time though...)
// Fetch the Initiators
List<URI> initiatorURIs = new ArrayList<URI>();
List<Initiator> initiators = new ArrayList<Initiator>();
for (String initiatorId : exportMask.getInitiators()) {
Initiator initiator = _dbClient.queryObject(Initiator.class, URI.create(initiatorId));
if (initiator != null) {
initiators.add(initiator);
initiatorURIs.add(initiator.getId());
}
}
if (!exportMask.hasAnyVolumes()) {
// Fetch the targets
List<URI> targets = new ArrayList<URI>();
for (String targetId : exportMask.getStoragePorts()) {
targets.add(URI.create(targetId));
}
// If some invalid export mask exists
if (exportMask.getNativeId() != null) {
exportMask.setNativeId("");
_dbClient.updateAndReindexObject(exportMask);
}
// The default completer passed in is for add volume, create correct one
TaskCompleter createCompleter = new ExportMaskCreateCompleter(exportGroupURI, exportMaskURI, initiatorURIs, volumeMap, stepId);
device.doExportCreate(array, exportMask, volumeMap, initiators, targets, createCompleter);
} else {
device.doExportAddVolumes(array, exportMask, initiators, volumeMap, completer);
}
} catch (Exception ex) {
_log.error("Failed to create or add volumes to export mask for XIV: ", ex);
VPlexApiException vplexex = DeviceControllerExceptions.vplex.addStepsForCreateVolumesFailed(ex);
WorkflowStepCompleter.stepFailed(stepId, vplexex);
}
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskCreateCompleter in project coprhd-controller by CoprHD.
the class VnxExportOperations method createOrGrowStorageGroup.
private CIMObjectPath[] createOrGrowStorageGroup(StorageSystem storage, URI exportMaskURI, VolumeURIHLU[] volumeURIHLUs, List<Initiator> initiatorList, List<URI> targetURIList, TaskCompleter completer) throws Exception {
// TODO - Refactor createOrGrowStorageGroup by moving code for creating an empty storage group
// to its own createStorageGroup method which calls exposePaths with null for initiators
// and targets
_log.info("{} createOrGrowStorageGroup START...", storage.getSerialNumber());
try {
List<CIMObjectPath> paths = new ArrayList<CIMObjectPath>();
Map<String, CIMObjectPath> existingHwStorageIds = getStorageHardwareIds(storage);
// If so, we need to register that initiator as the same name as the existing initiators. (CTRL-8407)
if (initiatorList != null) {
for (Initiator initiator : initiatorList) {
updateInitiatorBasedOnPeers(storage, existingHwStorageIds, initiator);
if (initiator != null) {
_log.info("After updateIntiatorBasedOnPeers : {} {}", initiator.getHostName(), initiator.toString());
}
}
}
Multimap<String, String> existingTargets = createStorageHWIDs(storage, existingHwStorageIds, initiatorList, completer);
if (initiatorList != null && existingTargets.keySet().size() == initiatorList.size()) {
_log.info(String.format("All the initiators are known to the array and have target endpoints: %s\n." + "These are the targets %s", Joiner.on(',').join(existingTargets.entries()), Joiner.on(',').join(targetURIList)));
}
Multimap<URI, Initiator> targetPortsToInitiators = HashMultimap.create();
// Some of the Initiators are already registered partially on the array based on pre existing zoning
// COP-16954 We need to manually register them, the Initiators will have HardwareId created but,
// The registration is not complete.. createHardwareIDs method above will include those Initiators
_log.info("Preregistered Target and Initiator ports processing .. Start");
// Map to hash translations
HashMap<String, URI> targetPortMap = new HashMap<>();
for (String initPort : existingTargets.keySet()) {
_log.info("InitiatorPort {} and TargetStoragePort {}", initPort, existingTargets.get(initPort));
// CLARIION+CKM00115001014+PORT+50:06:01:61:3E:A0:45:79]
if (!WWNUtility.isValidNoColonWWN(initPort)) {
_log.info("InitiatorPort {} is not a valid FC WWN so ignore it", initPort);
continue;
}
Collection<String> targetPorts = existingTargets.get(initPort);
for (String targetPortGuid : targetPorts) {
URI targetPortURI = targetPortMap.get(targetPortGuid);
if (targetPortURI == null) {
targetPortURI = getStoragePortURI(targetPortGuid);
targetPortMap.put(targetPortGuid, targetPortURI);
}
Initiator translatedInitiator = getInitiatorForWWN(initPort);
_log.info("Calculating Initiator {} and Target {}", translatedInitiator, targetPortURI);
if (targetPortURI != null && translatedInitiator != null) {
targetPortsToInitiators.put(targetPortURI, translatedInitiator);
} else {
_log.info("Initiator WWN {} translation was null or targetPort is null {}", initPort, targetPortURI);
}
}
}
_log.info("Preregistered Target and Initiator ports processing .. End");
List<URI> volumeURIs = new ArrayList<URI>();
if (volumeURIHLUs != null && volumeURIHLUs.length > 0) {
for (VolumeURIHLU volumeURIHLU : volumeURIHLUs) {
volumeURIs.add(volumeURIHLU.getVolumeURI());
}
}
if (initiatorList == null || initiatorList.isEmpty()) {
_log.info("InitiatorList is null or Empty so call exposePathsWithVolumesOnly");
paths.addAll(Arrays.asList(exposePathsWithVolumesOnly(storage, exportMaskURI, volumeURIHLUs)));
} else {
ExportMask mask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
for (Initiator initiator : initiatorList) {
// TODO - Ask Tom is there is a reason why we should not do this instead of old code
List<URI> tzTargets = ExportUtils.getInitiatorPortsInMask(mask, initiator, _dbClient);
_log.info("Calculating Intiator {} and Targets {}", initiator, tzTargets);
if (!tzTargets.isEmpty()) {
for (URI targetURI : tzTargets) {
targetPortsToInitiators.put(targetURI, initiator);
}
}
}
_log.info("Call manuallyRegisterHostInitiators with {} ", targetPortsToInitiators.toString());
// Register the initiator to target port mappings
manuallyRegisterHostInitiators(storage, targetPortsToInitiators);
// CTRL-9086
// Modify the list of initiators list to match what is being mapped. If there are any initiators
// that are passed to the ExposePaths call that weren't manuallyRegistered (above), then those
// initiators will automatically get mapped all the array's StoragePorts.
//
// If the targetPortsToInitiators MultiMap is empty, then we will send all the initiators.
// Presumably, in this situation there are already some existing mappings for the initiators,
// so would just need to call ExposePaths with those initiators, so that they get added to the
// StorageGroup
List<Initiator> initiatorsToExpose = initiatorList;
if (!targetPortsToInitiators.isEmpty()) {
Map<URI, Initiator> uniqueInitiatorMap = new HashMap<>();
for (Collection<Initiator> initiatorCollection : targetPortsToInitiators.asMap().values()) {
for (Initiator initiator : initiatorCollection) {
uniqueInitiatorMap.put(initiator.getId(), initiator);
}
}
initiatorsToExpose = new ArrayList<>(uniqueInitiatorMap.values());
// confused about the initiators.
if (completer instanceof ExportMaskCreateCompleter) {
ExportMaskCreateCompleter createCompleter = ((ExportMaskCreateCompleter) completer);
List<URI> removedInitiators = new ArrayList<>();
List<URI> maskInitiators = StringSetUtil.stringSetToUriList(mask.getInitiators());
for (URI maskInitiator : maskInitiators) {
if (!uniqueInitiatorMap.containsKey(maskInitiator)) {
mask.removeInitiator(maskInitiator);
removedInitiators.add(maskInitiator);
}
}
_dbClient.updateObject(mask);
if (!removedInitiators.isEmpty()) {
_log.info(String.format("The following initiators will not be mapped, hence they will be " + "removed from the initiator list of ExportMask %s (%s): %s", mask.getMaskName(), mask.getId(), Joiner.on(',').join(removedInitiators)));
}
// Adjust the completer's initiator list
createCompleter.removeInitiators(removedInitiators);
}
}
_log.info(String.format("ExposePaths will be called with these initiators: %s", Joiner.on(',').join(Collections2.transform(initiatorsToExpose, CommonTransformerFunctions.fctnInitiatorToPortName()))));
// Add all the initiators to the StorageGroup
paths.addAll(Arrays.asList(exposePathsWithVolumesAndInitiatorsOnly(storage, exportMaskURI, volumeURIHLUs, initiatorsToExpose)));
}
ExportOperationContext.insertContextOperation(completer, VnxExportOperationContext.OPERATION_ADD_VOLUMES_TO_STORAGE_GROUP, volumeURIs);
_log.info("{} createOrGrowStorageGroup END...", storage.getSerialNumber());
return paths.toArray(new CIMObjectPath[paths.size()]);
} catch (WBEMException e) {
_log.error("Problem making SMI-S call: ", e);
throw e;
} catch (Exception e) {
_log.error("Unexpected error: createOrGrowStorageGroup failed.", e);
throw e;
}
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskCreateCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method addStepsForExportMaskCreate.
/**
* Handles adding ExportMask creation into the export workflow.
*
* @param blockObjectMap
* the map of URIs to block volumes for export
* @param workflow
* the controller Workflow
* @param vplexSystem
* a StorageSystem objet representing the VPLEX
* @param exportGroup
* the ViPR ExportGroup in question
* @param storageViewStepId
* the current workflow step id, to be updated on return
* @param exportMask
* the ExportMask object to be created
* @return the workflow step id
*/
private String addStepsForExportMaskCreate(Map<URI, Integer> blockObjectMap, Workflow workflow, StorageSystem vplexSystem, ExportGroup exportGroup, String storageViewStepId, ExportMask exportMask) {
_log.info("adding step to create export mask: " + exportMask.getMaskName());
List<URI> inits = new ArrayList<URI>();
for (String init : exportMask.getInitiators()) {
inits.add(URI.create(init));
}
// Make the targets for this host.
List<URI> hostTargets = new ArrayList<URI>();
for (String targetId : exportMask.getStoragePorts()) {
hostTargets.add(URI.create(targetId));
}
String maskingStep = workflow.createStepId();
ExportTaskCompleter exportTaskCompleter = new ExportMaskCreateCompleter(exportGroup.getId(), exportMask.getId(), inits, blockObjectMap, maskingStep);
// Add a step to export on the VPlex. They call this a Storage View.
Workflow.Method storageViewExecuteMethod = new Workflow.Method(CREATE_STORAGE_VIEW, vplexSystem.getId(), exportGroup.getId(), exportMask.getId(), blockObjectMap, inits, hostTargets, exportTaskCompleter);
// Workflow.Method storageViewRollbackMethod = new Workflow.Method(ROLLBACK_METHOD_NULL);
Workflow.Method storageViewRollbackMethod = deleteStorageViewMethod(vplexSystem.getId(), exportGroup.getId(), exportMask.getId(), true);
storageViewStepId = workflow.createStep("storageView", String.format("Create VPLEX Storage View for ExportGroup %s Mask %s", exportGroup.getId(), exportMask.getMaskName()), storageViewStepId, vplexSystem.getId(), vplexSystem.getSystemType(), this.getClass(), storageViewExecuteMethod, storageViewRollbackMethod, maskingStep);
return storageViewStepId;
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskCreateCompleter in project coprhd-controller by CoprHD.
the class VPlexVmaxMaskingOrchestrator method createOrAddVolumesToExportMask.
/**
* Create an ExportMask on the VMAX if it does not exist. Otherwise, just add the indicated
* volumes to the ExportMask.
*/
@Override
public void createOrAddVolumesToExportMask(URI arrayURI, URI exportGroupURI, URI exportMaskURI, Map<URI, Integer> volumeMap, List<URI> initiatorURIs2, TaskCompleter completer, String stepId) {
try {
WorkflowStepCompleter.stepExecuting(stepId);
StorageSystem array = _dbClient.queryObject(StorageSystem.class, arrayURI);
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
// If the exportMask isn't found, or has been deleted, fail, ask user to retry.
if (exportMask == null || exportMask.getInactive()) {
_log.info(String.format("ExportMask %s deleted or inactive, failing", exportMaskURI));
ServiceError svcerr = VPlexApiException.errors.createBackendExportMaskDeleted(exportMaskURI.toString(), arrayURI.toString());
WorkflowStepCompleter.stepFailed(stepId, svcerr);
return;
}
// Protect concurrent operations by locking {host, array} dupple.
// Lock will be released when workflow step completes.
List<String> lockKeys = ControllerLockingUtil.getHostStorageLockKeys(_dbClient, ExportGroupType.Host, StringSetUtil.stringSetToUriList(exportMask.getInitiators()), arrayURI);
getWorkflowService().acquireWorkflowStepLocks(stepId, lockKeys, LockTimeoutValue.get(LockType.VPLEX_BACKEND_EXPORT));
// Refresh the ExportMask
BlockStorageDevice device = _blockController.getDevice(array.getSystemType());
exportMask = refreshExportMask(array, device, exportMask);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_009);
if (!exportMask.hasAnyVolumes()) {
// We are creating this ExportMask on the hardware! (Maybe not the first time though...)
// Fetch the Initiators
List<URI> initiatorURIs = new ArrayList<URI>();
List<Initiator> initiators = new ArrayList<Initiator>();
for (String initiatorId : exportMask.getInitiators()) {
Initiator initiator = _dbClient.queryObject(Initiator.class, URI.create(initiatorId));
if (initiator != null) {
initiators.add(initiator);
initiatorURIs.add(initiator.getId());
}
}
// Fetch the targets
List<URI> targets = new ArrayList<URI>();
for (String targetId : exportMask.getStoragePorts()) {
targets.add(URI.create(targetId));
}
// The default completer passed in is for add volume, create correct one
completer = new ExportMaskCreateCompleter(exportGroupURI, exportMaskURI, initiatorURIs, volumeMap, stepId);
// Note that there should not be any code after the call to the device as the completer
// will be invoked causing the workflow to continue execution with the next step.
device.doExportCreate(array, exportMask, volumeMap, initiators, targets, completer);
} else {
List<URI> initiatorURIs = new ArrayList<URI>();
List<Initiator> initiators = new ArrayList<Initiator>();
for (String initiatorId : exportMask.getInitiators()) {
Initiator initiator = _dbClient.queryObject(Initiator.class, URI.create(initiatorId));
if (initiator != null) {
initiators.add(initiator);
initiatorURIs.add(initiator.getId());
}
}
// Note that there should not be any code after the call to the device as the completer
// will be invoked causing the workflow to continue execution with the next step.
device.doExportAddVolumes(array, exportMask, initiators, volumeMap, completer);
}
} catch (Exception ex) {
_log.error("Failed to create or add volumes to export mask for vmax: ", ex);
VPlexApiException vplexex = DeviceControllerExceptions.vplex.addStepsForCreateVolumesFailed(ex);
WorkflowStepCompleter.stepFailed(stepId, vplexex);
}
}
Aggregations