Search in sources :

Example 16 with VPlexStorageViewInfo

use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.

the class VPlexDeviceController method findHLUsForInitiators.

/**
 * @param vplexStorageSystem
 * @param exportGroup
 * @param initiatorURIs
 * @param mustHaveAllPorts
 * @return
 * @throws Exception
 */
public Set<Integer> findHLUsForInitiators(StorageSystem vplexStorageSystem, ExportGroup exportGroup, List<URI> initiatorURIs, boolean mustHaveAllPorts) throws Exception {
    long startTime = System.currentTimeMillis();
    Set<Integer> usedHLUs = new HashSet<Integer>();
    VPlexApiClient client = VPlexControllerUtils.getVPlexAPIClient(_vplexApiFactory, vplexStorageSystem, _dbClient);
    URI srcVarrayURI = exportGroup.getVirtualArray();
    /**
     * Find used HLUs here for VPLEX local and distributed
     */
    _log.info("varray uri :{} Vplex URI :{}", srcVarrayURI, vplexStorageSystem.getId());
    String vplexClusterName = VPlexUtil.getVplexClusterName(srcVarrayURI, vplexStorageSystem.getId(), client, _dbClient);
    _log.info("vplexClusterName :{}", vplexClusterName);
    Iterator<Initiator> inits = _dbClient.queryIterativeObjects(Initiator.class, initiatorURIs);
    Boolean[] doRefresh = new Boolean[] { new Boolean(true) };
    List<String> initiatorNames = getInitiatorNames(vplexStorageSystem.getSerialNumber(), vplexClusterName, client, inits, doRefresh);
    List<VPlexStorageViewInfo> storageViewInfos = client.getStorageViewsContainingInitiators(vplexClusterName, initiatorNames);
    _log.info("initiatorNames {}", initiatorNames);
    if (exportGroup.hasAltVirtualArray(vplexStorageSystem.getId().toString())) {
        // If there is an alternate Varray entry for this Vplex, it indicates we have HA volumes.
        URI haVarrayURI = URI.create(exportGroup.getAltVirtualArrays().get(vplexStorageSystem.getId().toString()));
        _log.info("haVarrayURI :{} Vplex URI :{}", haVarrayURI, vplexStorageSystem.getId());
        String vplexHAClusterName = VPlexUtil.getVplexClusterName(haVarrayURI, vplexStorageSystem.getId(), client, _dbClient);
        _log.info("vplexHAClusterName :{}", vplexHAClusterName);
        inits = _dbClient.queryIterativeObjects(Initiator.class, initiatorURIs);
        Boolean[] doRefreshHa = new Boolean[] { new Boolean(true) };
        List<String> haInitiatorNames = getInitiatorNames(vplexStorageSystem.getSerialNumber(), vplexHAClusterName, client, inits, doRefreshHa);
        storageViewInfos.addAll(client.getStorageViewsContainingInitiators(vplexHAClusterName, haInitiatorNames));
    }
    for (VPlexStorageViewInfo storageViewInfo : storageViewInfos) {
        if (storageViewInfo != null && !CollectionUtils.isEmpty(storageViewInfo.getWwnToHluMap())) {
            _log.info("storageViewInfo.getWwnToHluMap() :{}", storageViewInfo.getWwnToHluMap());
            usedHLUs.addAll(storageViewInfo.getWwnToHluMap().values());
        }
    }
    _log.info(String.format("HLUs found for Initiators { %s }: %s", Joiner.on(',').join(initiatorNames), usedHLUs));
    long totalTime = System.currentTimeMillis() - startTime;
    _log.info(String.format("find used HLUs for Initiators took %f seconds", (double) totalTime / (double) 1000));
    return usedHLUs;
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) Initiator(com.emc.storageos.db.client.model.Initiator) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) HashSet(java.util.HashSet)

Example 17 with VPlexStorageViewInfo

use of com.emc.storageos.vplex.api.VPlexStorageViewInfo 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);
    }
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) StringMap(com.emc.storageos.db.client.model.StringMap) ArrayList(java.util.ArrayList) ExportDeleteCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportDeleteCompleter) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ExportMask(com.emc.storageos.db.client.model.ExportMask) ExportWorkflowEntryPoints(com.emc.storageos.volumecontroller.impl.block.ExportWorkflowEntryPoints) Workflow(com.emc.storageos.workflow.Workflow) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) NetworkZoningParam(com.emc.storageos.networkcontroller.impl.NetworkZoningParam) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient)

Example 18 with VPlexStorageViewInfo

use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.

the class VPlexDeviceController method storageViewRemoveInitiators.

/**
 * Workflow step to remove an initiator from a single Storage View as given by the ExportMask URI.
 * Note there is a dependence on ExportMask name equaling the Storage View name.
 * Note that arguments must match storageViewRemoveInitiatorsMethod above (except stepId).
 *
 * @param vplexURI
 *            -- URI of Vplex Storage System.
 * @param exportGroupURI
 *            -- URI of Export Group.
 * @param exportMaskURI
 *            -- URI of one ExportMask. Call only processes indicaated mask.
 * @param initiatorURIs
 *            -- URIs of Initiators to be removed.
 * @param targetURIs
 *            -- optional targets to be removed from the Storage View.
 *            If non null, a list of URIs for VPlex front-end ports that will be removed from Storage View.
 * @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 storageViewRemoveInitiators(URI vplexURI, URI exportGroupURI, URI exportMaskURI, List<URI> initiatorURIs, List<URI> targetURIs, TaskCompleter taskCompleter, String rollbackContextKey, String stepId) throws WorkflowException {
    ExportMaskRemoveInitiatorCompleter completer = null;
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        List<URI> initiatorIdsToProcess = new ArrayList<>(initiatorURIs);
        completer = new ExportMaskRemoveInitiatorCompleter(exportGroupURI, exportMaskURI, initiatorURIs, stepId);
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplexURI, client, _dbClient);
        Map<String, String> targetPortMap = VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName);
        VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
        _log.info("Refreshing ExportMask {}", exportMask.getMaskName());
        VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, targetPortMap, _networkDeviceController);
        // 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> addedInitiators = new ArrayList<>();
                if (context.getOperations() != null) {
                    _log.info("Handling removeInitiators 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_INITIATORS_TO_STORAGE_VIEW.equals(operation.getOperation())) {
                            addedInitiators = (List<URI>) operation.getArgs().get(0);
                            _log.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 (URI initiator : initiatorIdsToProcess) {
                    if (addedInitiators == null || !addedInitiators.contains(initiator)) {
                        completer.removeInitiator(initiator);
                    }
                }
                if (addedInitiators == null || addedInitiators.isEmpty()) {
                    _log.info("There was no context found for add initiator. 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.
                initiatorIdsToProcess.clear();
                initiatorIdsToProcess.addAll(addedInitiators);
            }
        }
        // validate the remove initiator operation against the export mask volumes
        List<URI> volumeURIList = (exportMask.getUserAddedVolumes() != null) ? URIUtil.toURIList(exportMask.getUserAddedVolumes().values()) : new ArrayList<URI>();
        if (volumeURIList.isEmpty()) {
            _log.warn("volume URI list for validating remove initiators is empty...");
        }
        ExportMaskValidationContext ctx = new ExportMaskValidationContext();
        ctx.setStorage(vplex);
        ctx.setExportMask(exportMask);
        ctx.setBlockObjects(volumeURIList, _dbClient);
        ctx.setAllowExceptions(!WorkflowService.getInstance().isStepInRollbackState(stepId));
        validator.removeInitiators(ctx).validate();
        // Invoke artificial failure to simulate invalid storageview name on vplex
        InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_060);
        // removing all storage ports but leaving the existing initiators and volumes.
        if (!exportMask.hasAnyExistingInitiators() && !exportMask.hasAnyExistingVolumes()) {
            if (targetURIs != null && targetURIs.isEmpty() == false) {
                List<PortInfo> targetPortInfos = new ArrayList<PortInfo>();
                List<URI> targetsAddedToStorageView = new ArrayList<URI>();
                for (URI target : targetURIs) {
                    // Do not try to remove a port twice.
                    if (!exportMask.getStoragePorts().contains(target.toString())) {
                        continue;
                    }
                    // Build the PortInfo structure for the port to be added
                    StoragePort port = getDataObject(StoragePort.class, target, _dbClient);
                    PortInfo pi = new PortInfo(port.getPortNetworkId().toUpperCase().replaceAll(":", ""), null, port.getPortName(), null);
                    targetPortInfos.add(pi);
                    targetsAddedToStorageView.add(target);
                }
                if (!targetPortInfos.isEmpty()) {
                    // Remove the targets from the VPLEX
                    client.removeTargetsFromStorageView(exportMask.getMaskName(), targetPortInfos);
                }
            }
        }
        // Update the initiators in the ExportMask.
        List<PortInfo> initiatorPortInfo = new ArrayList<PortInfo>();
        for (URI initiatorURI : initiatorIdsToProcess) {
            Initiator initiator = getDataObject(Initiator.class, initiatorURI, _dbClient);
            // We don't want to remove existing initiator, unless this is a rollback step
            if (exportMask.hasExistingInitiator(initiator) && !WorkflowService.getInstance().isStepInRollbackState(stepId)) {
                continue;
            }
            PortInfo portInfo = new PortInfo(initiator.getInitiatorPort().toUpperCase().replaceAll(":", ""), initiator.getInitiatorNode().toUpperCase().replaceAll(":", ""), initiator.getLabel(), getVPlexInitiatorType(initiator));
            initiatorPortInfo.add(portInfo);
        }
        // Remove the initiators if there aren't any existing volumes, unless this is a rollback step or validation is disabled.
        if (!initiatorPortInfo.isEmpty() && (!exportMask.hasAnyExistingVolumes() || !validatorConfig.isValidationEnabled() || WorkflowService.getInstance().isStepInRollbackState(stepId))) {
            String lockName = null;
            boolean lockAcquired = false;
            try {
                ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
                String clusterId = ConnectivityUtil.getVplexClusterForVarray(exportGroup.getVirtualArray(), vplexURI, _dbClient);
                lockName = _vplexApiLockManager.getLockName(vplexURI, clusterId);
                lockAcquired = _vplexApiLockManager.acquireLock(lockName, LockTimeoutValue.get(LockType.VPLEX_API_LIB));
                if (!lockAcquired) {
                    throw VPlexApiException.exceptions.couldNotObtainConcurrencyLock(vplex.getLabel());
                }
                // Remove the targets from the VPLEX
                // Test mechanism to invoke a failure. No-op on production systems.
                InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_016);
                client.removeInitiatorsFromStorageView(exportMask.getMaskName(), vplexClusterName, initiatorPortInfo);
            } finally {
                if (lockAcquired) {
                    _vplexApiLockManager.releaseLock(lockName);
                }
            }
        }
        completer.ready(_dbClient);
    } catch (VPlexApiException vae) {
        _log.error("Exception removing initiator from Storage View: " + vae.getMessage(), vae);
        failStep(completer, stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception removing initiator from Storage View: " + ex.getMessage(), ex);
        String opName = ResourceOperationTypeEnum.DELETE_STORAGE_VIEW_INITIATOR.getName();
        ServiceError serviceError = VPlexApiException.errors.storageViewRemoveInitiatorFailed(opName, ex);
        failStep(completer, stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) StoragePort(com.emc.storageos.db.client.model.StoragePort) ExportMaskRemoveInitiatorCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskRemoveInitiatorCompleter) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) PortInfo(com.emc.storageos.vplex.api.clientdata.PortInfo) ExportMaskValidationContext(com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) Initiator(com.emc.storageos.db.client.model.Initiator) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) ExportOperationContext(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext) ExportOperationContextOperation(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 19 with VPlexStorageViewInfo

use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.

the class VPlexDeviceController method storageViewRemoveStoragePorts.

/**
 * Workflow Step to remove storage ports from Storage View.
 * Note arguments (except stepId) must match storageViewRemoveStoragePortsMethod above.
 *
 * @param vplexURI
 *            -- URI of VPlex StorageSystem
 * @param exportURI
 *            -- ExportGroup URI
 * @param maskURI
 *            -- ExportMask URI.
 * @param targetURIs
 *            -- list of targets URIs (VPLEX FE ports) to be removed.
 *            If non null, the targets (VPlex front end ports) indicated by the targetURIs will be removed
 *            from the Storage View.
 * @param rollbackContextKey
 *            -- Context token for rollback processing
 * @param stepId
 *            -- Workflow step id.
 * @throws WorkflowException
 */
public void storageViewRemoveStoragePorts(URI vplexURI, URI exportURI, URI maskURI, List<URI> targetURIs, String rollbackContextKey, String stepId) throws DeviceControllerException {
    ExportMaskRemoveInitiatorCompleter completer = null;
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        completer = new ExportMaskRemoveInitiatorCompleter(exportURI, maskURI, new ArrayList<URI>(), stepId);
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        ExportMask exportMask = _dbClient.queryObject(ExportMask.class, maskURI);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplexURI, client, _dbClient);
        Map<String, String> targetPortMap = VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName);
        VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
        _log.info("Refreshing ExportMask {}", exportMask.getMaskName());
        VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, targetPortMap, _networkDeviceController);
        // get the context from the task completer, in case this is a rollback.
        if (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> addedTargets = new ArrayList<>();
                if (context.getOperations() != null) {
                    _log.info("Handling storageViewRemoveStoragePorts 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_TARGETS_TO_STORAGE_VIEW.equals(operation.getOperation())) {
                            addedTargets = (List<URI>) operation.getArgs().get(0);
                            _log.info(String.format("Removing target port(s) %s from storage view %s as part of rollback", Joiner.on(',').join(addedTargets), exportMask.getMaskName()));
                        }
                    }
                }
                if (addedTargets == null || addedTargets.isEmpty()) {
                    _log.info("There was no context found for add target. So there is nothing to rollback.");
                    completer.ready(_dbClient);
                    return;
                }
                // Change the list of targets to process to the list
                // that successfully were added during addStoragePorts.
                targetURIs.clear();
                targetURIs.addAll(addedTargets);
            }
        }
        // validate the remove storage port operation against the export mask volumes
        // this is conceptually the same as remove initiators, so will validate with volumes
        List<URI> volumeURIList = (exportMask.getUserAddedVolumes() != null) ? URIUtil.toURIList(exportMask.getUserAddedVolumes().values()) : new ArrayList<URI>();
        if (volumeURIList.isEmpty()) {
            _log.warn("volume URI list for validating remove initiators is empty...");
        }
        // removing all storage ports but leaving the existing initiators and volumes.
        if (!exportMask.hasAnyExistingInitiators() && !exportMask.hasAnyExistingVolumes()) {
            ExportMaskValidationContext ctx = new ExportMaskValidationContext();
            ctx.setStorage(vplex);
            ctx.setExportMask(exportMask);
            ctx.setBlockObjects(volumeURIList, _dbClient);
            ctx.setAllowExceptions(!WorkflowService.getInstance().isStepInRollbackState(stepId));
            validator.removeInitiators(ctx).validate();
            if (targetURIs != null && targetURIs.isEmpty() == false) {
                List<PortInfo> targetPortInfos = new ArrayList<PortInfo>();
                List<URI> targetsToRemoveFromStorageView = new ArrayList<URI>();
                for (URI target : targetURIs) {
                    // Do not try to remove a port twice.
                    if (!exportMask.getStoragePorts().contains(target.toString())) {
                        continue;
                    }
                    // Build the PortInfo structure for the port to be added
                    StoragePort port = getDataObject(StoragePort.class, target, _dbClient);
                    PortInfo pi = new PortInfo(port.getPortNetworkId().toUpperCase().replaceAll(":", ""), null, port.getPortName(), null);
                    targetPortInfos.add(pi);
                    targetsToRemoveFromStorageView.add(target);
                }
                if (!targetPortInfos.isEmpty()) {
                    // Remove the targets from the VPLEX
                    client.removeTargetsFromStorageView(exportMask.getMaskName(), targetPortInfos);
                    // Remove the targets to the database.
                    for (URI target : targetsToRemoveFromStorageView) {
                        exportMask.removeTarget(target);
                    }
                    _dbClient.updateObject(exportMask);
                }
            }
        }
        completer.ready(_dbClient);
    } catch (VPlexApiException vae) {
        _log.error("Exception removing storage ports from Storage View: " + vae.getMessage(), vae);
        failStep(completer, stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception removing storage ports from Storage View: " + ex.getMessage(), ex);
        String opName = ResourceOperationTypeEnum.DELETE_STORAGE_VIEW_STORAGEPORTS.getName();
        ServiceError serviceError = VPlexApiException.errors.storageViewRemoveStoragePortFailed(opName, ex);
        failStep(completer, stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) StoragePort(com.emc.storageos.db.client.model.StoragePort) ExportMaskRemoveInitiatorCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskRemoveInitiatorCompleter) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) PortInfo(com.emc.storageos.vplex.api.clientdata.PortInfo) ExportMaskValidationContext(com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) ExportOperationContext(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext) ExportOperationContextOperation(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 20 with VPlexStorageViewInfo

use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.

the class VPlexCommunicationInterface method updateUnmanagedVolume.

/**
 * Updates an existing UnManagedVolume with the latest info from
 * the VPLEX virtual volume.
 *
 * @param info a VPlexVirtualVolumeInfo descriptor
 * @param vplex the VPLEX storage system managing the volume
 * @param volume the existing UnManagedVolume
 * @param volumesToCgs a Map of volume labels to consistency group names
 * @param allVPools cache of all virtual pools for filtering
 */
private void updateUnmanagedVolume(VPlexVirtualVolumeInfo info, StorageSystem vplex, UnManagedVolume volume, Map<String, String> volumesToCgs, Map<String, String> clusterIdToNameMap, Map<String, String> varrayToClusterIdMap, Map<String, String> distributedDevicePathToClusterMap, Map<String, String> backendVolumeGuidToVvolGuidMap, Map<String, Set<VPlexStorageViewInfo>> volumeToStorageViewMap, Collection<VirtualPool> allVpools) {
    s_logger.info("Updating UnManagedVolume {} with latest from VPLEX volume {}", volume.getLabel(), info.getName());
    volume.setStorageSystemUri(vplex.getId());
    volume.setNativeGuid(info.getPath());
    volume.setLabel(info.getName());
    volume.setWwn(info.getWwn());
    volume.getUnmanagedExportMasks().clear();
    volume.getInitiatorUris().clear();
    volume.getInitiatorNetworkIds().clear();
    // set volume characteristics and volume information
    StringSetMap unManagedVolumeInformation = new StringSetMap();
    StringMap unManagedVolumeCharacteristics = new StringMap();
    // Set up default MAXIMUM_IO_BANDWIDTH and MAXIMUM_IOPS
    StringSet bwValues = new StringSet();
    bwValues.add("0");
    if (unManagedVolumeInformation.get(SupportedVolumeInformation.EMC_MAXIMUM_IO_BANDWIDTH.toString()) == null) {
        unManagedVolumeInformation.put(SupportedVolumeInformation.EMC_MAXIMUM_IO_BANDWIDTH.toString(), bwValues);
    } else {
        unManagedVolumeInformation.get(SupportedVolumeInformation.EMC_MAXIMUM_IO_BANDWIDTH.toString()).replace(bwValues);
    }
    StringSet iopsVal = new StringSet();
    iopsVal.add("0");
    if (unManagedVolumeInformation.get(SupportedVolumeInformation.EMC_MAXIMUM_IOPS.toString()) == null) {
        unManagedVolumeInformation.put(SupportedVolumeInformation.EMC_MAXIMUM_IOPS.toString(), iopsVal);
    } else {
        unManagedVolumeInformation.get(SupportedVolumeInformation.EMC_MAXIMUM_IOPS.toString()).replace(iopsVal);
    }
    // check if volume is part of a consistency group, and set the name if so
    if (volumesToCgs.containsKey(info.getName())) {
        unManagedVolumeCharacteristics.put(SupportedVolumeCharacterstics.IS_VOLUME_ADDED_TO_CONSISTENCYGROUP.toString(), TRUE);
        StringSet set = new StringSet();
        set.add(volumesToCgs.get(info.getName()));
        unManagedVolumeInformation.put(SupportedVolumeInformation.VPLEX_CONSISTENCY_GROUP_NAME.toString(), set);
    } else {
        unManagedVolumeCharacteristics.put(SupportedVolumeCharacterstics.IS_VOLUME_ADDED_TO_CONSISTENCYGROUP.toString(), FALSE);
    }
    // set system type
    StringSet systemTypes = new StringSet();
    systemTypes.add(vplex.getSystemType());
    unManagedVolumeInformation.put(SupportedVolumeInformation.SYSTEM_TYPE.toString(), systemTypes);
    // set volume capacity
    // For Vplex virtual volumes set allocated capacity to 0 (cop-18608)
    StringSet provCapacity = new StringSet();
    provCapacity.add(String.valueOf(info.getCapacityBytes()));
    StringSet allocatedCapacity = new StringSet();
    allocatedCapacity.add(String.valueOf(0));
    unManagedVolumeInformation.put(SupportedVolumeInformation.PROVISIONED_CAPACITY.toString(), provCapacity);
    unManagedVolumeInformation.put(SupportedVolumeInformation.ALLOCATED_CAPACITY.toString(), allocatedCapacity);
    // set vplex virtual volume properties
    unManagedVolumeCharacteristics.put(SupportedVolumeCharacterstics.IS_VPLEX_VOLUME.toString(), TRUE);
    StringSet locality = new StringSet();
    locality.add(info.getLocality());
    unManagedVolumeInformation.put(SupportedVolumeInformation.VPLEX_LOCALITY.toString(), locality);
    StringSet supportingDevice = new StringSet();
    supportingDevice.add(info.getSupportingDevice());
    unManagedVolumeInformation.put(SupportedVolumeInformation.VPLEX_SUPPORTING_DEVICE_NAME.toString(), supportingDevice);
    StringSet volumeClusters = new StringSet();
    volumeClusters.addAll(info.getClusters());
    unManagedVolumeInformation.put(SupportedVolumeInformation.VPLEX_CLUSTER_IDS.toString(), volumeClusters);
    StringSet accesses = new StringSet();
    accesses.add(Volume.VolumeAccessState.READWRITE.getState());
    unManagedVolumeInformation.put(SupportedVolumeInformation.ACCESS.toString(), accesses);
    // set supported vpool list
    StringSet matchedVPools = new StringSet();
    String highAvailability = info.getLocality().equals(LOCAL) ? VirtualPool.HighAvailabilityType.vplex_local.name() : VirtualPool.HighAvailabilityType.vplex_distributed.name();
    s_logger.info("finding valid virtual pools for UnManagedVolume {}", volume.getLabel());
    for (VirtualPool vpool : allVpools) {
        // - The vpool is RPVPLEX and this is a VPLEX local volume (likely a journal)
        if (!vpool.getHighAvailability().equals(highAvailability) && !(VirtualPool.vPoolSpecifiesRPVPlex(vpool) && highAvailability.equals(VirtualPool.HighAvailabilityType.vplex_local.name()))) {
            s_logger.info("   virtual pool {} is not valid because " + "its high availability setting does not match the unmanaged volume", vpool.getLabel());
            continue;
        }
        // If the volume is in a CG, the vpool must specify multi-volume consistency.
        Boolean mvConsistency = vpool.getMultivolumeConsistency();
        if ((TRUE.equals(unManagedVolumeCharacteristics.get(SupportedVolumeCharacterstics.IS_VOLUME_ADDED_TO_CONSISTENCYGROUP.toString()))) && ((mvConsistency == null) || (mvConsistency == Boolean.FALSE))) {
            s_logger.info("   virtual pool {} is not valid because it does not have the " + "multi-volume consistency flag set, and the unmanaged volume is in a consistency group", vpool.getLabel());
            continue;
        }
        // VPool must be assigned to a varray corresponding to volumes clusters.
        StringSet varraysForVpool = vpool.getVirtualArrays();
        for (String varrayId : varraysForVpool) {
            String varrayClusterId = varrayToClusterIdMap.get(varrayId);
            if (null == varrayClusterId) {
                varrayClusterId = ConnectivityUtil.getVplexClusterForVarray(URI.create(varrayId), vplex.getId(), _dbClient);
                varrayToClusterIdMap.put(varrayId, varrayClusterId);
            }
            if (!ConnectivityUtil.CLUSTER_UNKNOWN.equals(varrayClusterId)) {
                String varrayClusterName = clusterIdToNameMap.get(varrayClusterId);
                if (volumeClusters.contains(varrayClusterName)) {
                    matchedVPools.add(vpool.getId().toString());
                    break;
                }
            }
        }
        if (!matchedVPools.contains(vpool.getId().toString())) {
            s_logger.info("   virtual pool {} is not valid because " + "the volume resides on a cluster that does not match the varray(s) associated with the vpool", vpool.getLabel());
        }
    }
    // set thin provisioning state from virtual-volume thin-enabled property
    String thinlyProvisioned = info.isThinEnabled() ? TRUE : FALSE;
    unManagedVolumeCharacteristics.put(SupportedVolumeCharacterstics.IS_THINLY_PROVISIONED.toString(), thinlyProvisioned);
    // add this info to the unmanaged volume object
    volume.setVolumeCharacterstics(unManagedVolumeCharacteristics);
    volume.setVolumeInformation(unManagedVolumeInformation);
    // discover backend volume data
    String discoveryMode = ControllerUtils.getPropertyValueFromCoordinator(_coordinator, VplexBackendIngestionContext.DISCOVERY_MODE);
    if (!VplexBackendIngestionContext.DISCOVERY_MODE_INGESTION_ONLY.equals(discoveryMode)) {
        try {
            VplexBackendIngestionContext context = new VplexBackendIngestionContext(volume, _dbClient);
            context.setDistributedDevicePathToClusterMap(distributedDevicePathToClusterMap);
            context.discover();
            for (UnManagedVolume bvol : context.getUnmanagedBackendVolumes()) {
                // map this backend volume's GUID to its parent front-end volume GUID
                backendVolumeGuidToVvolGuidMap.put(bvol.getNativeGuid(), volume.getNativeGuid());
                // check if this backend volume is a full copy (and is target of clone)
                // if so, write this volume's GUID to the parent vvol's LOCAL_REPLICA_SOURCE_VOLUME
                // so that we can swap it out for the backend parent vvol's GUID
                String isFullCopyStr = bvol.getVolumeCharacterstics().get(SupportedVolumeCharacterstics.IS_FULL_COPY.toString());
                boolean isFullCopy = (null != isFullCopyStr && Boolean.parseBoolean(isFullCopyStr));
                if (isFullCopy) {
                    String fullCopySourceBvol = VplexBackendIngestionContext.extractValueFromStringSet(SupportedVolumeInformation.LOCAL_REPLICA_SOURCE_VOLUME.name(), bvol.getVolumeInformation());
                    if (fullCopySourceBvol != null && !fullCopySourceBvol.isEmpty()) {
                        StringSet set = new StringSet();
                        set.add(fullCopySourceBvol);
                        volume.putVolumeInfo(SupportedVolumeInformation.LOCAL_REPLICA_SOURCE_VOLUME.name(), set);
                        volume.putVolumeCharacterstics(SupportedVolumeCharacterstics.IS_FULL_COPY.toString(), Boolean.TRUE.toString());
                    }
                }
                // check if this backend volume has a replica (and is source of clone)
                // if so, write this volume's GUID to the parent vvol's FULL_COPIES
                // so that we can swap it out for the backend parent vvol's GUID
                String hasReplicasStr = bvol.getVolumeCharacterstics().get(SupportedVolumeCharacterstics.HAS_REPLICAS.toString());
                boolean hasReplicas = (null != hasReplicasStr && Boolean.parseBoolean(hasReplicasStr));
                if (hasReplicas) {
                    StringSet fullCopyTargetBvols = bvol.getVolumeInformation().get(SupportedVolumeInformation.FULL_COPIES.name());
                    if (fullCopyTargetBvols != null && !fullCopyTargetBvols.isEmpty()) {
                        // if this backend volume has FULL_COPIES, add them
                        // to the parent virtual volume's FULL_COPIES
                        // and make HAS_REPLICAS is set.
                        StringSet parentSet = volume.getVolumeInformation().get(SupportedVolumeInformation.FULL_COPIES.name());
                        if (parentSet == null) {
                            parentSet = new StringSet();
                        }
                        for (String fullCopyTargetBvol : fullCopyTargetBvols) {
                            parentSet.add(fullCopyTargetBvol);
                        }
                        volume.putVolumeInfo(SupportedVolumeInformation.FULL_COPIES.name(), parentSet);
                        volume.putVolumeCharacterstics(SupportedVolumeCharacterstics.HAS_REPLICAS.toString(), Boolean.TRUE.toString());
                    }
                }
                // set replica state on parent if found in backend volume
                String replicaState = VplexBackendIngestionContext.extractValueFromStringSet(SupportedVolumeInformation.REPLICA_STATE.name(), bvol.getVolumeInformation());
                if (replicaState != null && !replicaState.isEmpty()) {
                    StringSet set = new StringSet();
                    set.add(replicaState);
                    volume.putVolumeInfo(SupportedVolumeInformation.REPLICA_STATE.name(), set);
                }
                // set sync active state on parent if found in backend volume
                String syncActive = VplexBackendIngestionContext.extractValueFromStringSet(SupportedVolumeInformation.IS_SYNC_ACTIVE.name(), bvol.getVolumeInformation());
                if (syncActive != null && !syncActive.isEmpty()) {
                    StringSet set = new StringSet();
                    set.add(syncActive);
                    volume.putVolumeInfo(SupportedVolumeInformation.IS_SYNC_ACTIVE.name(), set);
                }
            }
            s_logger.info(context.getPerformanceReport());
        } catch (Exception ex) {
            s_logger.warn("error discovering backend structure for {}: ", volume.getNativeGuid(), ex);
        // no need to throw further
        }
    }
    unManagedVolumeCharacteristics.put(SupportedVolumeCharacterstics.IS_INGESTABLE.toString(), TRUE);
    if (null == matchedVPools || matchedVPools.isEmpty()) {
        // clean all supported vpools.
        volume.getSupportedVpoolUris().clear();
        s_logger.info("No matching VPOOLS found for unmanaged volume " + volume.getLabel());
    } else {
        // replace with new StringSet
        volume.getSupportedVpoolUris().replace(matchedVPools);
        s_logger.info("Replaced Pools : {}", volume.getSupportedVpoolUris());
    }
    Set<VPlexStorageViewInfo> svs = volumeToStorageViewMap.get(info.getName());
    if (svs != null) {
        updateWwnAndHluInfo(volume, info.getName(), svs);
    }
}
Also used : StringSetMap(com.emc.storageos.db.client.model.StringSetMap) StringMap(com.emc.storageos.db.client.model.StringMap) VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) StringSet(com.emc.storageos.db.client.model.StringSet) VplexBackendIngestionContext(com.emc.storageos.vplexcontroller.VplexBackendIngestionContext) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) URISyntaxException(java.net.URISyntaxException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) BaseCollectionException(com.emc.storageos.plugins.BaseCollectionException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexCollectionException(com.emc.storageos.plugins.metering.vplex.VPlexCollectionException) IOException(java.io.IOException)

Aggregations

VPlexStorageViewInfo (com.emc.storageos.vplex.api.VPlexStorageViewInfo)21 URI (java.net.URI)18 VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)16 ExportMask (com.emc.storageos.db.client.model.ExportMask)15 ArrayList (java.util.ArrayList)15 NamedURI (com.emc.storageos.db.client.model.NamedURI)14 URISyntaxException (java.net.URISyntaxException)14 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)12 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)12 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)12 IOException (java.io.IOException)12 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)11 Initiator (com.emc.storageos.db.client.model.Initiator)10 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)10 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)10 ControllerException (com.emc.storageos.volumecontroller.ControllerException)10 WorkflowException (com.emc.storageos.workflow.WorkflowException)10 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)9 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)9 HashMap (java.util.HashMap)9