use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskRemoveVolumeCompleter in project coprhd-controller by CoprHD.
the class AbstractDefaultMaskingOrchestrator method generateExportMaskRemoveVolumesWorkflow.
/**
* Generate workflow steps to remove volumes from an export mask
*
* @param workflow
* workflow
* @param previousStep
* previous step ID
* @param storage
* storage system
* @param exportGroup
* export group
* @param exportMask
* export mask
* @param volumesToRemove
* volumes to remove
* @param initiators
* initiators that should be impacted
* @param completer
* completer
* @return step ID
* @throws Exception
*/
public String generateExportMaskRemoveVolumesWorkflow(Workflow workflow, String previousStep, StorageSystem storage, ExportGroup exportGroup, ExportMask exportMask, List<URI> volumesToRemove, List<URI> initiators, ExportTaskCompleter completer) throws Exception {
URI exportGroupURI = exportGroup.getId();
URI exportMaskURI = exportMask.getId();
URI storageURI = storage.getId();
String maskingStep = workflow.createStepId();
ExportTaskCompleter exportTaskCompleter;
if (completer != null) {
exportTaskCompleter = completer;
exportTaskCompleter.setOpId(maskingStep);
} else {
exportTaskCompleter = new ExportMaskRemoveVolumeCompleter(exportGroupURI, exportMask.getId(), volumesToRemove, maskingStep);
}
Workflow.Method maskingExecuteMethod = new Workflow.Method("doExportGroupRemoveVolumes", storageURI, exportGroupURI, exportMaskURI, volumesToRemove, initiators, exportTaskCompleter);
maskingStep = workflow.createStep(EXPORT_GROUP_MASKING_TASK, String.format("Removing volumes from mask %s (%s)", exportMask.getMaskName(), exportMask.getId().toString()), previousStep, storageURI, storage.getSystemType(), MaskingWorkflowEntryPoints.class, maskingExecuteMethod, null, maskingStep);
return maskingStep;
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskRemoveVolumeCompleter in project coprhd-controller by CoprHD.
the class MaskingWorkflowEntryPoints method rollbackExportGroupAddVolumes.
/**
* Rollback entry point. This is a wrapper around the exportGroupRemoveVolumes
* operation, which requires that we create a specific completer using the token
* that's passed in. This token is generated by the rollback processing.
*
* @param storageURI
* [in] - StorageSystem URI
* @param exportGroupURI
* [in] - ExportGroup URI
* @param exportGroupURIs
* [in] - All ExportGroup URIs that the export mask associates with
* @param exportMaskURI
* [in] - ExportMask URI
* @param volumeMap
* [in] - Map of Volume URI to HLU Integer value
* @param initiatorURIs
* [in] - Impacted initiators
* @param contextKey
* [in] - context token
* @param token
* [in] - String token generated by the rollback processing
* @throws ControllerException
*/
public void rollbackExportGroupAddVolumes(URI storageURI, URI exportGroupURI, List<URI> exportGroupURIs, URI exportMaskURI, Map<URI, Integer> volumeMap, List<URI> initiatorURIs, String contextKey, String token) throws ControllerException {
List<URI> list = new ArrayList<URI>();
list.addAll(volumeMap.keySet());
ExportTaskCompleter taskCompleter = new ExportMaskRemoveVolumeCompleter(exportGroupURI, exportMaskURI, list, token);
taskCompleter.setExportGroups(exportGroupURIs);
// in order to only perform rollback of operations we successfully performed.
try {
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(contextKey);
WorkflowService.getInstance().storeStepData(token, context);
} catch (ClassCastException e) {
_log.info("Step {} has stored step data other than ExportOperationContext. Exception: {}", token, e);
}
doExportGroupRemoveVolumes(storageURI, exportGroupURI, exportMaskURI, list, initiatorURIs, taskCompleter, token);
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskRemoveVolumeCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method addStepsForRemoveInitiators.
/**
* Add steps necessary for Export removeInitiators.
* This routine may be called multiple times for an Export Group on each
* exportMask that needs to be adjusted.
*
* @param vplex
* -- StorageSystem VPLEX
* @param workflow
* -- Workflow steps being added to
* @param exportGroup
* -- ExportGroup
* @param exportMask
* -- ExportMask being processed
* @param initiators
* -- List<Initiator> initiators being removed
* @param hostURI
* -- Host URI
* @param hostInitiatorURIs
* -- list of Host Initiators
* @param errorMessages
* -- collector for any validation-related error messages
* @param previousStep
* -- previous step to wait on
* @return String last step added to workflow; null if no steps added
* @throws Exception
*/
private String addStepsForRemoveInitiators(StorageSystem vplex, Workflow workflow, ExportRemoveInitiatorCompleter completer, ExportGroup exportGroup, ExportMask exportMask, List<Initiator> initiators, URI hostURI, List<URI> initiatorsAlreadyRemovedFromExportGroup, StringBuffer errorMessages, String previousStep) throws Exception {
String lastStep = previousStep;
// assemble a list of other ExportGroups that reference this ExportMask
List<ExportGroup> otherExportGroups = ExportUtils.getOtherExportGroups(exportGroup, exportMask, _dbClient);
_log.info(String.format("will be removing initiators %s for host %s mask %s (%s)", getInitiatorsWwnsString(initiators), hostURI.toString(), exportMask.getMaskName(), exportMask.getId()));
List<URI> hostInitiatorURIs = new ArrayList<URI>();
List<URI> removeInitiatorListURIs = new ArrayList<URI>();
for (Initiator initiator : initiators) {
// contained within this ExportMask (CTRL-12300)
if (exportMask.hasInitiator(initiator.getId().toString())) {
hostInitiatorURIs.add(initiator.getId());
}
// removeInitiatorListURIs is created to pass it to next method name addStepsForInitiatorRemoval
// we have filtering logic placed inside addStepsForInitiatorRemoval to take care of it.
removeInitiatorListURIs.add(initiator.getId());
}
// Determine the targets we should remove for the initiators being removed.
// Normally one or more targets will be removed for each initiator that
// is removed according to the zoning map.
List<URI> targetURIs = getTargetURIs(exportMask, hostInitiatorURIs);
_log.info(String.format("will be removing targets %s for host %s", targetURIs.toString(), hostURI.toString()));
// What is about to happen...
//
// 1. if all the initiators in the storage view are getting removed
// and there are no existing (external) initiators in the Export Mask
// then delete the storage view
//
// 2. if there are other ExportGroups referencing this ExportMask
// AND
// if there are no more of this ExportMask's initiators present
// in this ExportGroup's initiators
// THEN
// remove this ExportGroup's volumes
// that aren't also present in other ExportGroups
// from this ExportMask
// AND FINALLY
// remove the initiator(s) from the ExportGroup
// but NOT from the ExportMask
// (because other ExportGroups are referencing it still)
//
// 3. otherwise,
// just remove initiators from the storage view, and if removing
// all initiators, also remove any volumes present in the ExportGroup
boolean removeAllInits = (hostInitiatorURIs.size() >= exportMask.getInitiators().size());
boolean canDeleteMask = removeAllInits && !exportMask.hasAnyExistingInitiators();
if (canDeleteMask) {
if (!ExportUtils.exportMaskHasBothExclusiveAndSharedVolumes(exportGroup, otherExportGroups, exportMask)) {
_log.info("all initiators are being removed and no " + "other ExportGroups reference ExportMask {}", exportMask.getMaskName());
_log.info("creating a deleteStorageView workflow step for " + exportMask.getMaskName());
String exportMaskDeleteStep = workflow.createStepId();
Workflow.Method storageViewExecuteMethod = deleteStorageViewMethod(vplex.getId(), exportGroup.getId(), exportMask.getId(), false);
lastStep = workflow.createStep(DELETE_STORAGE_VIEW, String.format("Delete VPLEX Storage View %s for ExportGroup %s", exportMask.getMaskName(), exportGroup.getId()), lastStep, vplex.getId(), vplex.getSystemType(), this.getClass(), storageViewExecuteMethod, null, exportMaskDeleteStep);
// Add zoning step for deleting ExportMask
List<NetworkZoningParam> zoningParam = NetworkZoningParam.convertExportMasksToNetworkZoningParam(exportGroup.getId(), Collections.singletonList(exportMask.getId()), _dbClient);
Workflow.Method zoneMaskDeleteMethod = _networkDeviceController.zoneExportMasksDeleteMethod(zoningParam, StringSetUtil.stringSetToUriList(exportMask.getVolumes().keySet()));
Workflow.Method zoneNullRollbackMethod = _networkDeviceController.zoneNullRollbackMethod();
lastStep = workflow.createStep(null, "Zone delete mask: " + exportMask.getMaskName(), lastStep, nullURI, "network-system", _networkDeviceController.getClass(), zoneMaskDeleteMethod, zoneNullRollbackMethod, null);
} else {
// export Mask has shared and exclusive volumes, removing the volumes.
// The volumes can be taken from the export Group
List<URI> volumeURIList = URIUtil.toURIList(exportGroup.getVolumes().keySet());
if (!volumeURIList.isEmpty()) {
List<Volume> volumes = _dbClient.queryObject(Volume.class, volumeURIList);
String volumesForDisplay = Joiner.on(", ").join(Collections2.transform(volumes, CommonTransformerFunctions.fctnDataObjectToForDisplay()));
_log.info("there are some volumes that need to be removed: " + volumesForDisplay);
_log.info("creating a remove volumes workflow step with " + exportMask.getMaskName() + " for volumes " + CommonTransformerFunctions.collectionToString(volumeURIList));
completer.addExportMaskToRemovedVolumeMapping(exportMask.getId(), volumeURIList);
TaskCompleter taskCompleter = new ExportMaskRemoveVolumeCompleter(exportGroup.getId(), exportMask.getId(), volumeURIList, lastStep);
Workflow.Method storageViewRemoveVolume = storageViewRemoveVolumesMethod(vplex.getId(), exportGroup.getId(), exportMask.getId(), volumeURIList, lastStep, taskCompleter, null);
lastStep = workflow.createStep("removeVolumes", String.format("Removing volumes from export on storage array %s (%s) for export mask %s (%s)", vplex.getNativeGuid(), vplex.getId().toString(), exportMask.getMaskName(), exportMask.getId()), lastStep, vplex.getId(), vplex.getSystemType(), this.getClass(), storageViewRemoveVolume, rollbackMethodNullMethod(), null);
// Add zoning step for removing volumes
List<NetworkZoningParam> zoningParam = NetworkZoningParam.convertExportMasksToNetworkZoningParam(exportGroup.getId(), Collections.singletonList(exportMask.getId()), _dbClient);
Workflow.Method zoneRemoveVolumesMethod = _networkDeviceController.zoneExportRemoveVolumesMethod(zoningParam, volumeURIList);
lastStep = workflow.createStep(null, "Zone remove volumes mask: " + exportMask.getMaskName(), lastStep, nullURI, "network-system", _networkDeviceController.getClass(), zoneRemoveVolumesMethod, _networkDeviceController.zoneNullRollbackMethod(), null);
}
}
} else {
// this is just a simple initiator removal, so just do it...
lastStep = addStepsForInitiatorRemoval(vplex, workflow, completer, exportGroup, exportMask, removeInitiatorListURIs, targetURIs, lastStep, removeAllInits, hostURI, errorMessages);
}
return lastStep;
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskRemoveVolumeCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method storageViewAddVolumesRollback.
/**
* Rollback entry point. This is a wrapper around the exportRemoveVolumes
* operation, which requires that we create a specific completer using the token
* that's passed in. This token is generated by the rollback processing.
*
* @param vplexURI
* [in] - StorageSystem URI
* @param exportGroupURI
* [in] - ExportGroup URI
* @param exportMaskURI
* [in] - ExportMask URI
* @param volumeURIs
* [in] - Impacted volume URIs
* @param initiatorURIs
* [in] - List of Initiator URIs
* @param rollbackContextKey
* [in] - context token
* @param token
* [in] - String token generated by the rollback processing
* @throws ControllerException
*/
public void storageViewAddVolumesRollback(URI vplexURI, URI exportGroupURI, URI exportMaskURI, List<URI> volumeURIs, String rollbackContextKey, String token) throws ControllerException {
TaskCompleter taskCompleter = new ExportMaskRemoveVolumeCompleter(exportGroupURI, exportMaskURI, volumeURIs, token);
// in order to only perform rollback of operations we successfully performed.
try {
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(rollbackContextKey);
WorkflowService.getInstance().storeStepData(token, context);
storageViewRemoveVolumes(vplexURI, exportGroupURI, exportMaskURI, volumeURIs, rollbackContextKey, taskCompleter, rollbackContextKey, token);
} catch (Exception e) {
String message = String.format("Failed to remove Volume(s) %s on rollback from ExportGroup %s", Joiner.on(",").join(volumeURIs), exportGroupURI);
_log.error(message, e);
String opName = ResourceOperationTypeEnum.DELETE_EXPORT_VOLUME.getName();
ServiceError serviceError = VPlexApiException.errors.exportGroupRemoveVolumesFailed(Joiner.on(",").join(volumeURIs), exportGroupURI.toString(), opName, e);
taskCompleter.error(_dbClient, serviceError);
}
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskRemoveVolumeCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method storageViewRemoveVolumes.
/**
* @param client
* -- VPlexApiClient used for communication
* @param exportGroupURI
* -- Export Group
* @param exportMaskURI
* -- ExportMask corresponding to the StorageView
* @param volumeURIList
* -- URI of virtual volumes
* @param parentStepId
* -- Workflow parent step id
* @param taskCompleter
* -- the task completer, used to find the rollback context,
* which will be non-null in the case of rollback
* @param rollbackContextKey
* context key for rollback processing
* @param stepId
* -- Workflow step id
* @throws WorkflowException
*/
public void storageViewRemoveVolumes(URI vplexURI, URI exportGroupURI, URI exportMaskURI, List<URI> volumeURIList, String parentStepId, TaskCompleter taskCompleter, String rollbackContextKey, String stepId) throws WorkflowException {
ExportMaskRemoveVolumeCompleter completer = null;
ExportGroup exportGroup = null;
ExportMask exportMask = null;
try {
WorkflowStepCompleter.stepExecuting(stepId);
List<URI> volumeIdsToProcess = new ArrayList<>(volumeURIList);
exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
completer = new ExportMaskRemoveVolumeCompleter(exportGroup.getId(), exportMask.getId(), volumeURIList, stepId);
// get the context from the task completer, in case this is a rollback.
if (taskCompleter != null && rollbackContextKey != null) {
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(rollbackContextKey);
if (context != null) {
// a non-null context means this step is running as part of a rollback.
List<URI> addedVolumes = new ArrayList<>();
if (context.getOperations() != null) {
_log.info("Handling removeVolumes as a result of rollback");
ListIterator<ExportOperationContextOperation> li = context.getOperations().listIterator(context.getOperations().size());
while (li.hasPrevious()) {
ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
if (operation != null && VplexExportOperationContext.OPERATION_ADD_VOLUMES_TO_STORAGE_VIEW.equals(operation.getOperation())) {
addedVolumes = (List<URI>) operation.getArgs().get(0);
_log.info("Removing volumes {} as part of rollback", Joiner.on(',').join(addedVolumes));
}
}
if (addedVolumes == null || addedVolumes.isEmpty()) {
_log.info("There was no context found for add volumes. So there is nothing to rollback.");
completer.ready(_dbClient);
return;
}
}
// change the list of initiators to process to the
// list that successfully were added during addInitiators.
volumeIdsToProcess.clear();
volumeIdsToProcess.addAll(addedVolumes);
}
}
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
// Removes the specified volumes from the storage view
// and updates the export mask.
removeVolumesFromStorageViewAndMask(client, exportMask, volumeIdsToProcess, parentStepId);
completer.ready(_dbClient);
} catch (VPlexApiException vae) {
_log.error("Exception removing volumes from Storage View: " + vae.getMessage(), vae);
failStep(completer, stepId, vae);
} catch (Exception ex) {
_log.error("Exception removing volumes from Storage View: " + ex.getMessage(), ex);
String opName = ResourceOperationTypeEnum.REMOVE_STORAGE_VIEW_VOLUME.getName();
ServiceError serviceError = VPlexApiException.errors.storageViewRemoveVolumeFailed(exportMask != null ? exportMask.getMaskName() : "none", opName, ex);
failStep(completer, stepId, serviceError);
}
}
Aggregations