use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportRemoveVolumeCompleter in project coprhd-controller by CoprHD.
the class BlockStorageDeviceTest method testExportRemoveVolumes.
@Test
public void testExportRemoveVolumes() {
ExportGroup exportGroup = getExportGroup();
ExportMask exportMask = getExportMask();
List<Volume> volumes = getVolumes(_storageSystem);
List<URI> volumeURIs = new ArrayList<URI>();
for (Volume volume : volumes) {
volumeURIs.add(volume.getId());
}
String token = UUID.randomUUID().toString() + UUID.randomUUID().toString();
ExportTaskCompleter taskCompleter = new ExportRemoveVolumeCompleter(exportGroup.getId(), volumeURIs, token);
_deviceController.doExportRemoveVolumes(_storageSystem, exportMask, volumeURIs, null, taskCompleter);
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportRemoveVolumeCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method exportGroupRemoveVolumes.
/*
* (non-Javadoc)
*
* @see com.emc.storageos.volumecontroller.impl.vplex.VplexController#exportRemoveVolume(java.net.URI, java.net.URI,
* java.net.URI,
* java.lang.String)
*/
@Override
public void exportGroupRemoveVolumes(URI vplexURI, URI exportURI, List<URI> volumeURIs, String opId) throws ControllerException {
String volListStr = "";
ExportRemoveVolumeCompleter completer = null;
boolean hasSteps = false;
try {
_log.info("entering export group remove volumes");
WorkflowStepCompleter.stepExecuting(opId);
completer = new ExportRemoveVolumeCompleter(exportURI, volumeURIs, opId);
volListStr = Joiner.on(',').join(volumeURIs);
validator.volumeURIs(volumeURIs, false, false, ValCk.ID);
Workflow workflow = _workflowService.getNewWorkflow(this, EXPORT_GROUP_REMOVE_VOLUMES, false, opId);
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
ExportGroup exportGroup = getDataObject(ExportGroup.class, exportURI, _dbClient);
List<ExportMask> exportMasks = ExportMaskUtils.getExportMasks(_dbClient, exportGroup, vplex.getId());
StringBuffer errorMessages = new StringBuffer();
boolean isValidationNeeded = validatorConfig.isValidationEnabled();
_log.info("Orchestration level validation needed : {}", isValidationNeeded);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
// For safety, run remove volumes serially
String previousStep = null;
for (ExportMask exportMask : exportMasks) {
if (exportMask.getInactive()) {
_log.info(String.format("ExportMask %s (%s) is inactive, skipping", exportMask.getMaskName(), exportMask.getId()));
continue;
}
String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplexURI, client, _dbClient);
Map<String, String> targetPortToPwwnMap = VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName);
VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
_log.info("Refreshing ExportMask {}", exportMask.getMaskName());
VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, targetPortToPwwnMap, _networkDeviceController);
List<URI> volumeURIList = new ArrayList<URI>();
List<URI> remainingVolumesInMask = new ArrayList<URI>();
if (exportMask.getVolumes() != null && !exportMask.getVolumes().isEmpty()) {
// note that this is the assumed behavior even for the
// situation in which this export mask is in use by other
// export groups... see CTRL-3941
// assemble a list of other ExportGroups that reference this ExportMask
List<ExportGroup> otherExportGroups = ExportUtils.getOtherExportGroups(exportGroup, exportMask, _dbClient);
if (otherExportGroups != null && !otherExportGroups.isEmpty()) {
// Gets the list of volume URIs that are not other Export Groups
volumeURIList = getVolumeListDiff(exportGroup, exportMask, otherExportGroups, volumeURIs);
} else {
volumeURIList = volumeURIs;
}
Map<URI, BlockObject> blockObjectMap = VPlexUtil.translateRPSnapshots(_dbClient, volumeURIList);
volumeURIList.clear();
volumeURIList.addAll(blockObjectMap.keySet());
volumeURIList = ExportMaskUtils.filterVolumesByExportMask(volumeURIList, exportMask);
for (String volumeURI : exportMask.getVolumes().keySet()) {
remainingVolumesInMask.add(URI.create(volumeURI));
}
remainingVolumesInMask.removeAll(volumeURIList);
}
_log.info(String.format("exportGroupRemove: mask %s volumes to process: %s", exportMask.getMaskName(), volumeURIList.toString()));
// Fetch exportMask again as exportMask zoning Map might have changed in zoneExportRemoveVolumes
exportMask = _dbClient.queryObject(ExportMask.class, exportMask.getId());
boolean existingVolumes = exportMask.hasAnyExistingVolumes();
// The useradded - existing initiators enhancement made in refreshExportMask
// guarantees that all the discovered initiators are added to userAdded,
// irrespective of whether it's already registered on the array manually.
boolean existingInitiators = exportMask.hasAnyExistingInitiators();
boolean canMaskBeDeleted = remainingVolumesInMask.isEmpty() && !existingInitiators && !existingVolumes;
if (!canMaskBeDeleted) {
_log.info("this mask is not empty, so just updating: " + exportMask.getMaskName());
completer.addExportMaskToRemovedVolumeMapping(exportMask.getId(), volumeURIList);
Workflow.Method storageViewRemoveVolume = storageViewRemoveVolumesMethod(vplex.getId(), exportGroup.getId(), exportMask.getId(), volumeURIList, opId, completer, null);
previousStep = 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()), previousStep, 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);
previousStep = workflow.createStep(null, "Zone remove volumes mask: " + exportMask.getMaskName(), previousStep, nullURI, "network-system", _networkDeviceController.getClass(), zoneRemoveVolumesMethod, _networkDeviceController.zoneNullRollbackMethod(), null);
hasSteps = true;
/**
* TODO
* ExportremoveVolumeCompleter should be enhanced to remove export mask from export group if last volume removed.
* We already take care of this.
*/
} else {
_log.info("this mask is empty of ViPR-managed volumes, and there are no existing volumes or initiators, so deleting: " + exportMask.getMaskName());
List<NetworkZoningParam> zoningParams = NetworkZoningParam.convertExportMasksToNetworkZoningParam(exportURI, Collections.singletonList(exportMask.getId()), _dbClient);
hasSteps = true;
String exportMaskDeleteStep = workflow.createStepId();
Workflow.Method deleteStorageView = deleteStorageViewMethod(vplexURI, exportURI, exportMask.getId(), false);
previousStep = workflow.createStep(DELETE_STORAGE_VIEW, String.format("Deleting storage view: %s (%s)", exportMask.getMaskName(), exportMask.getId()), previousStep, vplexURI, vplex.getSystemType(), this.getClass(), deleteStorageView, null, exportMaskDeleteStep);
// Unzone step (likely just a FCZoneReference removal since this is remove volume only)
previousStep = workflow.createStep(ZONING_STEP, "Zoning subtask for export-group: " + exportURI, previousStep, NullColumnValueGetter.getNullURI(), "network-system", _networkDeviceController.getClass(), _networkDeviceController.zoneExportRemoveVolumesMethod(zoningParams, volumeURIs), null, workflow.createStepId());
}
}
if (hasSteps) {
String message = errorMessages.toString();
if (isValidationNeeded && !message.isEmpty()) {
_log.error("Error Message {}", errorMessages);
List<Volume> volumes = _dbClient.queryObject(Volume.class, volumeURIs);
String volumesForDisplay = Joiner.on(", ").join(Collections2.transform(volumes, CommonTransformerFunctions.fctnDataObjectToForDisplay()));
throw DeviceControllerException.exceptions.removeVolumesValidationError(volumesForDisplay, vplex.forDisplay(), message);
}
workflow.executePlan(completer, String.format("Sucessfully removed volumes or deleted Storage View: %s (%s)", exportGroup.getLabel(), exportGroup.getId()));
} else {
completer.ready(_dbClient);
}
} catch (VPlexApiException vae) {
String message = String.format("Failed to remove Volume %s from ExportGroup %s", volListStr, exportURI);
_log.error(message, vae);
failStep(completer, opId, vae);
} catch (Exception ex) {
String message = String.format("Failed to remove Volume %s from ExportGroup %s", volListStr, exportURI);
_log.error(message, ex);
String opName = ResourceOperationTypeEnum.DELETE_EXPORT_VOLUME.getName();
ServiceError serviceError = VPlexApiException.errors.exportGroupRemoveVolumesFailed(volListStr, exportURI.toString(), opName, ex);
failStep(completer, opId, serviceError);
}
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportRemoveVolumeCompleter in project coprhd-controller by CoprHD.
the class BlockStorageDeviceTest method testExportRemoveVolume.
@Test
public void testExportRemoveVolume() {
ExportGroup exportGroup = getExportGroup();
ExportMask exportMask = getExportMask();
List<Volume> volumes = getVolumes(_storageSystem);
Volume volume = volumes.get(0);
List<URI> volumeURIs = new ArrayList<URI>(1);
volumeURIs.add(volume.getId());
String token = UUID.randomUUID().toString() + UUID.randomUUID().toString();
ExportTaskCompleter taskCompleter = new ExportRemoveVolumeCompleter(exportGroup.getId(), volumeURIs, token);
_deviceController.doExportRemoveVolume(_storageSystem, exportMask, volume.getId(), null, taskCompleter);
}
Aggregations