use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportDeleteCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method exportGroupDelete.
/*
* (non-Javadoc)
*
* @see com.emc.storageos.volumecontroller.impl.vplex.VplexController#exportGroupDelete(java.net.URI, java.net.URI,
* java.lang.String)
*/
@Override
public void exportGroupDelete(URI vplex, URI export, String opId) throws ControllerException {
ExportDeleteCompleter completer = null;
try {
_log.info("Entering exportGroupDelete");
WorkflowStepCompleter.stepExecuting(opId);
completer = new ExportDeleteCompleter(export, opId);
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplex, _dbClient);
ExportGroup exportGroup = null;
try {
exportGroup = getDataObject(ExportGroup.class, export, _dbClient);
} catch (VPlexApiException ve) {
// This exception is caught specifically to handle rollback
// cases. The export group will be marked inactive before this
// method is called hence it will always throw this exception in
// rollback scenarios. Hence this exception is caught as storage
// view will be already deleted due to rollback steps.
completer.ready(_dbClient);
return;
}
_log.info("Attempting to delete ExportGroup " + exportGroup.getGeneratedName() + " on VPLEX " + vplexSystem.getLabel());
Workflow workflow = _workflowService.getNewWorkflow(this, "exportGroupDelete", false, opId);
StringBuffer errorMessages = new StringBuffer();
boolean isValidationNeeded = validatorConfig.isValidationEnabled() && !ExportUtils.checkIfExportGroupIsRP(exportGroup);
_log.info("Orchestration level validation needed : {}", isValidationNeeded);
List<ExportMask> exportMasks = ExportMaskUtils.getExportMasks(_dbClient, exportGroup, vplex);
if (exportMasks.isEmpty()) {
throw VPlexApiException.exceptions.exportGroupDeleteFailedNull(vplex.toString());
}
// back a failed export group creation.
if (!exportGroupMasksContainExportGroupVolume(exportGroup, exportMasks)) {
for (ExportMask exportMask : exportMasks) {
exportGroup.removeExportMask(exportMask.getId());
}
_dbClient.updateObject(exportGroup);
completer.ready(_dbClient);
return;
}
// Add a steps to remove exports on the VPlex.
List<URI> exportMaskUris = new ArrayList<URI>();
List<URI> volumeUris = new ArrayList<URI>();
String storageViewStepId = null;
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
for (ExportMask exportMask : exportMasks) {
if (exportMask.getStorageDevice().equals(vplex)) {
String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplex, client, _dbClient);
VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
_log.info("Refreshing ExportMask {}", exportMask.getMaskName());
Map<String, String> targetPortToPwwnMap = VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName);
VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, targetPortToPwwnMap, _networkDeviceController);
// assemble a list of other ExportGroups that reference this ExportMask
List<ExportGroup> otherExportGroups = ExportUtils.getOtherExportGroups(exportGroup, exportMask, _dbClient);
boolean existingVolumes = exportMask.hasAnyExistingVolumes();
boolean existingInitiators = exportMask.hasAnyExistingInitiators();
boolean removeVolumes = false;
List<URI> volumeURIList = new ArrayList<URI>();
if (!otherExportGroups.isEmpty()) {
if (exportGroup.getVolumes() != null) {
for (String volUri : exportGroup.getVolumes().keySet()) {
volumeURIList.add(URI.create(volUri));
}
}
volumeURIList = getVolumeListDiff(exportGroup, exportMask, otherExportGroups, volumeURIList);
if (!volumeURIList.isEmpty()) {
removeVolumes = true;
}
} else if (existingVolumes || existingInitiators) {
// initiators.
if (existingVolumes) {
_log.info("Storage view will not be deleted because Export Mask {} has existing volumes: {}", exportMask.getMaskName(), exportMask.getExistingVolumes());
}
if (existingInitiators) {
_log.info("Storage view will not be deleted because Export Mask {} has existing initiators: {}", exportMask.getMaskName(), exportMask.getExistingInitiators());
}
if (exportMask.getUserAddedVolumes() != null && !exportMask.getUserAddedVolumes().isEmpty()) {
StringMap volumes = exportMask.getUserAddedVolumes();
if (volumes != null) {
for (String vol : volumes.values()) {
URI volumeURI = URI.create(vol);
volumeURIList.add(volumeURI);
}
}
if (!volumeURIList.isEmpty()) {
removeVolumes = true;
}
}
} else {
_log.info("creating a deleteStorageView workflow step for " + exportMask.getMaskName());
String exportMaskDeleteStep = workflow.createStepId();
Workflow.Method storageViewExecuteMethod = deleteStorageViewMethod(vplex, exportGroup.getId(), exportMask.getId(), false);
storageViewStepId = workflow.createStep(DELETE_STORAGE_VIEW, String.format("Delete VPLEX Storage View %s for ExportGroup %s", exportMask.getMaskName(), export), storageViewStepId, vplexSystem.getId(), vplexSystem.getSystemType(), this.getClass(), storageViewExecuteMethod, null, exportMaskDeleteStep);
}
if (removeVolumes) {
_log.info("removing volumes: " + volumeURIList);
Workflow.Method method = ExportWorkflowEntryPoints.exportRemoveVolumesMethod(vplexSystem.getId(), export, volumeURIList);
storageViewStepId = workflow.createStep("removeVolumes", String.format("Removing volumes from export on storage array %s (%s)", vplexSystem.getNativeGuid(), vplexSystem.getId().toString()), storageViewStepId, NullColumnValueGetter.getNullURI(), vplexSystem.getSystemType(), ExportWorkflowEntryPoints.class, method, null, null);
}
_log.info("determining which volumes to remove from ExportMask " + exportMask.getMaskName());
exportMaskUris.add(exportMask.getId());
for (URI volumeUri : ExportMaskUtils.getVolumeURIs(exportMask)) {
if (exportGroup.hasBlockObject(volumeUri)) {
volumeUris.add(volumeUri);
_log.info(" this ExportGroup volume is a match: " + volumeUri);
} else {
_log.info(" this ExportGroup volume is not in this export mask, so skipping: " + volumeUri);
}
}
}
}
if (!exportMaskUris.isEmpty()) {
_log.info("exportGroupDelete export mask URIs: " + exportMaskUris);
_log.info("exportGroupDelete volume URIs: " + volumeUris);
String zoningStep = workflow.createStepId();
List<NetworkZoningParam> zoningParams = NetworkZoningParam.convertExportMasksToNetworkZoningParam(export, exportMaskUris, _dbClient);
Workflow.Method zoningExecuteMethod = _networkDeviceController.zoneExportMasksDeleteMethod(zoningParams, volumeUris);
workflow.createStep(ZONING_STEP, String.format("Delete ExportMasks %s for VPlex %s", export, vplex), storageViewStepId, nullURI, "network-system", _networkDeviceController.getClass(), zoningExecuteMethod, null, zoningStep);
}
String message = errorMessages.toString();
if (isValidationNeeded && !message.isEmpty()) {
_log.error("Error Message {}", errorMessages);
throw DeviceControllerException.exceptions.deleteExportGroupValidationError(exportGroup.forDisplay(), vplexSystem.forDisplay(), message);
}
// Start the workflow
workflow.executePlan(completer, "Successfully deleted ExportMasks for ExportGroup: " + export);
} catch (Exception ex) {
_log.error("Exception deleting ExportGroup: " + ex.getMessage());
String opName = ResourceOperationTypeEnum.DELETE_EXPORT_GROUP.getName();
ServiceError serviceError = VPlexApiException.errors.exportGroupDeleteFailed(opName, ex);
failStep(completer, opId, serviceError);
}
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportDeleteCompleter in project coprhd-controller by CoprHD.
the class ComputeSystemControllerImpl method deleteExportGroup.
public void deleteExportGroup(URI exportGroup, String stepId) {
try {
BlockExportController blockController = getController(BlockExportController.class, BlockExportController.EXPORT);
_dbClient.createTaskOpStatus(ExportGroup.class, exportGroup, stepId, ResourceOperationTypeEnum.DELETE_EXPORT_GROUP);
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_027);
blockController.exportGroupDelete(exportGroup, stepId);
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_028);
} catch (Exception ex) {
_log.error("Exception occured while deleting export group {}", exportGroup, ex);
// Clean up any pending tasks
ExportTaskCompleter taskCompleter = new ExportDeleteCompleter(exportGroup, false, stepId);
ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
taskCompleter.error(_dbClient, serviceError);
// Fail the step
WorkflowStepCompleter.stepFailed(stepId, DeviceControllerException.errors.jobFailed(ex));
}
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportDeleteCompleter in project coprhd-controller by CoprHD.
the class BlockStorageDeviceTest method testExportGroupDeletion.
@Test
public void testExportGroupDeletion() {
ExportGroup exportGroup = getExportGroup();
ExportMask exportMask = getExportMask();
String token = UUID.randomUUID().toString() + UUID.randomUUID().toString();
ExportTaskCompleter taskCompleter = new ExportDeleteCompleter(exportGroup.getId(), false, token);
_deviceController.doExportDelete(_storageSystem, exportMask, null, null, taskCompleter);
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportDeleteCompleter in project coprhd-controller by CoprHD.
the class BlockDeviceExportController method exportGroupDelete.
/**
* Delete the export.
*
* @param export URI of ExportGroup
* @param opId Operation ID
* @throws com.emc.storageos.volumecontroller.ControllerException
*/
@Override
public void exportGroupDelete(URI export, String opId) throws ControllerException {
ExportTaskCompleter taskCompleter = new ExportDeleteCompleter(export, false, opId);
Workflow workflow = null;
try {
ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, export);
if (exportGroup != null && exportGroup.getExportMasks() != null) {
workflow = _wfUtils.newWorkflow("exportGroupDelete", false, opId);
if (NullColumnValueGetter.isNullValue(exportGroup.getType())) {
// (VPLEX backend groups have a null export group type, for instance)
throw DeviceControllerException.exceptions.exportGroupDeleteUnsupported(exportGroup.forDisplay());
}
Set<URI> storageSystemURIs = new HashSet<URI>();
// Use temp set to prevent ConcurrentModificationException
List<ExportMask> tempExportMasks = ExportMaskUtils.getExportMasks(_dbClient, exportGroup);
for (ExportMask tempExportMask : tempExportMasks) {
List<String> lockKeys = ControllerLockingUtil.getHostStorageLockKeys(_dbClient, ExportGroup.ExportGroupType.valueOf(exportGroup.getType()), StringSetUtil.stringSetToUriList(exportGroup.getInitiators()), tempExportMask.getStorageDevice());
boolean acquiredLocks = _wfUtils.getWorkflowService().acquireWorkflowLocks(workflow, lockKeys, LockTimeoutValue.get(LockType.EXPORT_GROUP_OPS));
if (!acquiredLocks) {
throw DeviceControllerException.exceptions.failedToAcquireLock(lockKeys.toString(), "ExportGroupDelete: " + exportGroup.getLabel());
}
if (tempExportMask != null && tempExportMask.getVolumes() != null) {
List<URI> uriList = getExportRemovableObjects(exportGroup, tempExportMask);
Map<URI, List<URI>> storageToVolumes = getStorageToVolumes(uriList);
for (URI storageURI : storageToVolumes.keySet()) {
if (!storageSystemURIs.contains(storageURI)) {
storageSystemURIs.add(storageURI);
_wfUtils.generateExportGroupDeleteWorkflow(workflow, null, null, storageURI, export);
}
}
} else {
exportGroup.removeExportMask(tempExportMask.getId());
_dbClient.updateObject(exportGroup);
}
}
workflow.executePlan(taskCompleter, "Removed export from all devices.");
} else {
taskCompleter.ready(_dbClient);
}
} catch (Exception ex) {
String message = "exportGroupDelete caught an exception.";
_log.error(message, ex);
if (workflow != null) {
_wfUtils.getWorkflowService().releaseAllWorkflowLocks(workflow);
}
ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
taskCompleter.error(_dbClient, serviceError);
}
}
Aggregations