Search in sources :

Example 6 with ExportMaskValidationContext

use of com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext in project coprhd-controller by CoprHD.

the class VmaxExportOperations method removeInitiators.

@Override
public void removeInitiators(StorageSystem storage, URI exportMaskURI, List<URI> volumeURIList, List<Initiator> initiatorList, List<URI> targetURIList, TaskCompleter taskCompleter) throws DeviceControllerException {
    _log.info("{} removeInitiators START...", storage == null ? null : storage.getSerialNumber());
    String clusterName = getClusterNameFromInitiators(initiatorList);
    if (clusterName == null) {
        final String logMsg = "All initiators should belong to the same cluster or not have a cluster name at all";
        _log.error(String.format("removeInitiator failed - maskName: %s", exportMaskURI.toString()), logMsg);
        String opName = ResourceOperationTypeEnum.DELETE_EXPORT_INITIATOR.getName();
        ServiceError serviceError = DeviceControllerException.errors.jobFailedOp(opName);
        taskCompleter.error(_dbClient, serviceError);
        return;
    } else {
        CloseableIterator<CIMInstance> cigInstances = null;
        try {
            _log.info("removeInitiators: Export mask id: {}", exportMaskURI);
            if (volumeURIList != null) {
                _log.info("removeInitiators: volumes : {}", Joiner.on(',').join(volumeURIList));
            }
            _log.info("removeInitiators: initiators : {}", Joiner.on(',').join(initiatorList));
            if (targetURIList != null) {
                _log.info("removeInitiators: targets : {}", Joiner.on(',').join(targetURIList));
            }
            boolean isRollback = WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId());
            ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
            ExportMaskValidationContext ctx = new ExportMaskValidationContext();
            ctx.setStorage(storage);
            ctx.setExportMask(exportMask);
            ctx.setBlockObjects(volumeURIList, _dbClient);
            ctx.setInitiators(initiatorList);
            // Allow exceptions to be thrown when not rolling back.
            ctx.setAllowExceptions(!isRollback);
            validator.removeInitiators(ctx).validate();
            if (isRollback) {
                // Get the context from the task completer as this is a rollback.
                ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
                exportMaskRollback(storage, context, taskCompleter);
            } else {
                CIMArgument[] inArgs;
                CIMArgument[] outArgs;
                _log.info("Removing initiators ...");
                // Create a mapping of the InitiatorPort String to Initiator.
                Map<String, Initiator> nameToInitiator = new HashMap<String, Initiator>();
                for (Initiator initiator : initiatorList) {
                    String normalizedName = Initiator.normalizePort(initiator.getInitiatorPort());
                    nameToInitiator.put(normalizedName, initiator);
                }
                // We're going to get a mapping of which InitiatorGroups the initiators belong.
                // With this mapping we can remove initiators from their associated IGs sequentially
                ListMultimap<CIMObjectPath, String> igToInitiators = ArrayListMultimap.create();
                mapInitiatorsToInitiatorGroups(igToInitiators, storage, initiatorList);
                for (CIMObjectPath igPath : igToInitiators.keySet()) {
                    List<String> initiatorPorts = igToInitiators.get(igPath);
                    List<Initiator> initiatorsForIG = new ArrayList<Initiator>();
                    // Using the mapping, create a list of Initiator objects
                    for (String port : initiatorPorts) {
                        Initiator initiator = nameToInitiator.get(port);
                        if (initiator != null) {
                            initiatorsForIG.add(initiator);
                        }
                    }
                    boolean removingAllPortsInIG = initiatorPorts.size() == initiatorsForIG.size();
                    if (removingAllPortsInIG) {
                        // We are apparently trying to remove all the initiators in an Initiator Group.
                        // This is a special condition. It is not a case of removing the initiators
                        // from an individual group, we will instead treat this as a removal of the
                        // IG from the cascade-IG (thereby preventing access to the host pointed to
                        // by this IG).
                        _log.info(String.format("Request to remove all the initiators from IG %s, so we will remove the IG from the cascaded-IG", igPath.toString()));
                        ExportMask mask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
                        CIMObjectPath cigInMVPath = null;
                        CIMInstance mvInstance = _helper.getSymmLunMaskingView(storage, mask);
                        cigInstances = _helper.getAssociatorInstances(storage, mvInstance.getObjectPath(), null, SmisConstants.SE_INITIATOR_MASKING_GROUP, null, null, SmisConstants.PS_ELEMENT_NAME);
                        if (cigInstances.hasNext()) {
                            cigInMVPath = cigInstances.next().getObjectPath();
                        }
                        // Find the cascaded initiator group that this belongs to and remove the IG from it.
                        // Note: we should not be in here if the IG was associated directly to the MV. If the
                        // IG were related to the MV, then the masking orchestrator should have generated
                        // a workflow to delete the MV.
                        cigInstances = _helper.getAssociatorInstances(storage, igPath, null, SmisConstants.SE_INITIATOR_MASKING_GROUP, null, null, SmisConstants.PS_ELEMENT_NAME);
                        while (cigInstances.hasNext()) {
                            CIMObjectPath cigPath = cigInstances.next().getObjectPath();
                            if (!cigPath.equals(cigInMVPath)) {
                                // to remove the initiators from.
                                continue;
                            }
                            _log.info(String.format("Removing IG %s from CIG %s", igPath.toString(), cigPath.toString()));
                            inArgs = _helper.getRemoveIGFromCIG(igPath, cigPath);
                            outArgs = new CIMArgument[5];
                            _helper.invokeMethodSynchronously(storage, _cimPath.getControllerConfigSvcPath(storage), "RemoveMembers", inArgs, outArgs, null);
                            // Determine if the IG contains all initiators that were added by user/ViPR, and if
                            // the IG is no longer referenced by masking views or parent IGs. If so, it can be
                            // removed.
                            boolean removeIG = true;
                            for (Initiator initiator : initiatorsForIG) {
                                if (!mask.hasUserInitiator(initiator.getId())) {
                                    removeIG = false;
                                }
                            }
                            if (removeIG) {
                                List<CIMObjectPath> igList = new ArrayList<>();
                                igList.add(igPath);
                                this.checkIGsAndDeleteIfUnassociated(storage, igList);
                            }
                        }
                    } else {
                        inArgs = _helper.getRemoveInitiatorsFromMaskingGroupInputArguments(storage, igPath, initiatorsForIG);
                        outArgs = new CIMArgument[5];
                        _helper.invokeMethodSynchronously(storage, _cimPath.getControllerConfigSvcPath(storage), "RemoveMembers", inArgs, outArgs, null);
                    }
                }
                if (targetURIList != null && !targetURIList.isEmpty()) {
                    _log.info("Removing targets...");
                    URI pgURI = exportMask.getPortGroup();
                    if (!NullColumnValueGetter.isNullURI(pgURI)) {
                        StoragePortGroup portGroup = _dbClient.queryObject(StoragePortGroup.class, pgURI);
                        if (!portGroup.getMutable()) {
                            _log.info(String.format("The port group %s is immutable, done", portGroup.getNativeGuid()));
                            taskCompleter.ready(_dbClient);
                            return;
                        }
                    }
                    CIMInstance portGroupInstance = _helper.getPortGroupInstance(storage, exportMask.getMaskName());
                    if (null == portGroupInstance) {
                        String errMsg = String.format("removeInitiators failed - maskName %s : Port group not found ", exportMask.getMaskName());
                        ServiceError serviceError = DeviceControllerException.errors.jobFailedMsg(errMsg, null);
                        taskCompleter.error(_dbClient, serviceError);
                        return;
                    }
                    String pgGroupName = (String) portGroupInstance.getPropertyValue(SmisConstants.CP_ELEMENT_NAME);
                    // Get the current ports off of the storage group; only add the ones that aren't there already.
                    WBEMClient client = _helper.getConnection(storage).getCimClient();
                    List<String> storagePorts = _helper.getStoragePortsFromLunMaskingInstance(client, portGroupInstance);
                    Set<URI> storagePortURIs = new HashSet<>();
                    storagePortURIs.addAll(transform(ExportUtils.storagePortNamesToURIs(_dbClient, storagePorts), CommonTransformerFunctions.FCTN_STRING_TO_URI));
                    Set<URI> portsToRemove = intersection(newHashSet(targetURIList), storagePortURIs);
                    boolean removingLast = portsToRemove.size() == storagePortURIs.size();
                    if (!portsToRemove.isEmpty() && !removingLast) {
                        inArgs = _helper.getRemoveTargetPortsFromMaskingGroupInputArguments(storage, pgGroupName, Lists.newArrayList(portsToRemove));
                        outArgs = new CIMArgument[5];
                        _helper.invokeMethodSynchronously(storage, _cimPath.getControllerConfigSvcPath(storage), "RemoveMembers", inArgs, outArgs, null);
                    } else if (!removingLast) {
                        _log.info(String.format("Target ports already removed fom port group %s, likely by a previous operation.", pgGroupName));
                    } else {
                        // In this case, some programming, orchestration, or
                        // user-fiddling-with-things-outside-of-ViPR situation led us
                        // to this scenario.
                        // It's best to just print the ports and port group and leave it alone.
                        _log.error(String.format("Removing target ports would cause an empty port group %s, which is not allowed on VMAX.  Manual port removal may be required.", pgGroupName));
                    // This can lead to an inaccuracy in the ExportMask object, but may be recitified next time
                    // it's refreshed.
                    }
                }
            }
            _log.info(String.format("removeInitiators succeeded - maskName: %s", exportMaskURI.toString()));
            taskCompleter.ready(_dbClient);
        } catch (Exception e) {
            _log.error(String.format("removeInitiators failed - maskName: %s", exportMaskURI.toString()), e);
            String opName = ResourceOperationTypeEnum.DELETE_EXPORT_INITIATOR.getName();
            ServiceError serviceError = DeviceControllerException.errors.jobFailedOpMsg(opName, e.getMessage());
            taskCompleter.error(_dbClient, serviceError);
        } finally {
            if (cigInstances != null) {
                cigInstances.close();
            }
        }
    }
    _log.info("{} removeInitiators END...", storage == null ? null : storage.getSerialNumber());
}
Also used : StoragePortGroup(com.emc.storageos.db.client.model.StoragePortGroup) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URI(java.net.URI) CIMInstance(javax.cim.CIMInstance) Initiator(com.emc.storageos.db.client.model.Initiator) ExportOperationContext(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext) WBEMClient(javax.wbem.client.WBEMClient) Sets.newHashSet(com.google.common.collect.Sets.newHashSet) HashSet(java.util.HashSet) ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ExportMask(com.emc.storageos.db.client.model.ExportMask) CIMObjectPath(javax.cim.CIMObjectPath) SmisException(com.emc.storageos.volumecontroller.impl.smis.SmisException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) WBEMException(javax.wbem.WBEMException) ExportMaskValidationContext(com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext) CIMArgument(javax.cim.CIMArgument)

Example 7 with ExportMaskValidationContext

use of com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext in project coprhd-controller by CoprHD.

the class VPlexDeviceController method deleteStorageView.

/**
 * A Workflow Step to delete a VPlex Storage View.
 *
 * @param vplexURI vplex
 * @param exportMaskURI export mask
 * @param isRollbackStep is this being run as a rollback step?
 * @param stepId step ID
 * @throws WorkflowException
 */
public void deleteStorageView(URI vplexURI, URI exportGroupURI, URI exportMaskURI, boolean isRollbackStep, String stepId) throws WorkflowException {
    ExportMaskDeleteCompleter completer = null;
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        completer = new ExportMaskDeleteCompleter(exportGroupURI, exportMaskURI, stepId);
        completer.setRollingBack(isRollbackStep);
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        Boolean[] viewFound = new Boolean[] { new Boolean(false) };
        ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        if (exportMask != null) {
            String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplexURI, client, _dbClient);
            VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
            if (storageView != null) {
                // we can ignore this in the case of a missing storage view on the VPLEX, it has already been
                // deleted
                _log.info("Refreshing ExportMask {}", exportMask.getMaskName());
                VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName), _networkDeviceController);
            }
            if (exportMask.hasAnyExistingVolumes() || exportMask.hasAnyExistingInitiators()) {
                _log.warn("ExportMask {} still has non-ViPR-created existing volumes or initiators, " + "so ViPR will not remove it from the VPLEX device", exportMask.getMaskName());
            }
            if (exportMask.getInactive()) {
                _log.warn("ExportMask {} is already inactive, so there's " + "no need to delete it off the VPLEX", exportMask.getMaskName());
            } else {
                List<URI> volumeURIs = new ArrayList<URI>();
                if (exportMask.getUserAddedVolumes() != null && !exportMask.getUserAddedVolumes().isEmpty()) {
                    volumeURIs = StringSetUtil.stringSetToUriList(exportMask.getUserAddedVolumes().values());
                }
                List<Initiator> initiators = new ArrayList<>();
                if (exportMask.getUserAddedInitiators() != null && !exportMask.getUserAddedInitiators().isEmpty()) {
                    List<URI> initiatorURIs = StringSetUtil.stringSetToUriList(exportMask.getUserAddedInitiators().values());
                    initiators.addAll(_dbClient.queryObject(Initiator.class, initiatorURIs));
                }
                ExportMaskValidationContext ctx = new ExportMaskValidationContext();
                ctx.setStorage(vplex);
                ctx.setExportMask(exportMask);
                ctx.setBlockObjects(volumeURIs, _dbClient);
                ctx.setInitiators(initiators);
                ctx.setAllowExceptions(!WorkflowService.getInstance().isStepInRollbackState(stepId));
                validator.exportMaskDelete(ctx).validate();
                InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_084);
                // note: there's a chance if the existing storage view originally had only
                // storage ports configured in it, then it would be deleted by this
                _log.info("removing this export mask from VPLEX: " + exportMask.getMaskName());
                client.deleteStorageView(exportMask.getMaskName(), vplexClusterName, viewFound);
                if (viewFound[0]) {
                    _log.info("as expected, storage view was found for deletion on the VPLEX.");
                } else {
                    _log.info("storage view was not found on the VPLEX during deletion, " + "but no errors were encountered.");
                }
            }
            _log.info("Marking export mask for deletion from Vipr: " + exportMask.getMaskName());
            _dbClient.markForDeletion(exportMask);
            _log.info("updating ExportGroups containing this ExportMask");
            List<ExportGroup> exportGroups = ExportMaskUtils.getExportGroups(_dbClient, exportMask);
            for (ExportGroup exportGroup : exportGroups) {
                _log.info("Removing mask from ExportGroup " + exportGroup.getGeneratedName());
                exportGroup.removeExportMask(exportMaskURI);
                _dbClient.updateObject(exportGroup);
            }
        } else {
            _log.info("ExportMask to delete could not be found in database: " + exportMaskURI);
        }
        completer.ready(_dbClient);
    } catch (VPlexApiException vae) {
        _log.error("Exception deleting ExportMask: " + exportMaskURI, vae);
        failStep(completer, stepId, vae);
    } catch (DeviceControllerException ex) {
        _log.error("Exception deleting ExportMask: " + exportMaskURI, ex);
        failStep(completer, stepId, ex);
    } catch (Exception ex) {
        _log.error("Exception deleting ExportMask: " + exportMaskURI, ex);
        ServiceError svcError = VPlexApiException.errors.deleteStorageViewFailed(ex);
        failStep(completer, stepId, svcError);
    }
}
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) 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) ExportMaskDeleteCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskDeleteCompleter) 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) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 8 with ExportMaskValidationContext

use of com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext in project coprhd-controller by CoprHD.

the class VPlexDeviceController method exportGroupRemoveInitiators.

/*
     * (non-Javadoc)
     *
     * @see com.emc.storageos.volumecontroller.impl.vplex.VplexController#exportRemoveInitiator(java.net.URI,
     * java.net.URI, java.net.URI,
     * java.lang.String)
     */
@Override
public void exportGroupRemoveInitiators(URI vplexURI, URI exportURI, List<URI> initiatorURIs, String opId) throws ControllerException {
    try {
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        ExportGroup exportGroup = getDataObject(ExportGroup.class, exportURI, _dbClient);
        ExportRemoveInitiatorCompleter completer = new ExportRemoveInitiatorCompleter(exportURI, initiatorURIs, opId);
        Workflow workflow = _workflowService.getNewWorkflow(this, "exportRemoveInitiator", true, opId);
        // true if Workflow has a Step
        boolean hasStep = false;
        Initiator firstInitiator = _dbClient.queryObject(Initiator.class, initiatorURIs.get(0));
        StringBuffer errorMessages = new StringBuffer();
        boolean isValidationNeeded = validatorConfig.isValidationEnabled() && !ExportUtils.checkIfInitiatorsForRP(Arrays.asList(firstInitiator));
        _log.info("Orchestration level validation needed : {}", isValidationNeeded);
        _log.info("starting remove initiators for export group: " + exportGroup.toString());
        _log.info("request is to remove these initiators: " + initiatorURIs);
        initiatorURIs = VPlexUtil.filterInitiatorsForVplex(_dbClient, initiatorURIs);
        // get a map of host URI to a list of Initiators in that Host
        Map<URI, List<Initiator>> hostInitiatorsMap = VPlexUtil.makeHostInitiatorsMap(initiatorURIs, _dbClient);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        // Loop, processing each host separately.
        for (URI hostURI : hostInitiatorsMap.keySet()) {
            _log.info("setting up initiator removal for host " + hostURI);
            // Get the initiators (and initiator URIs) for this host
            List<Initiator> initiators = hostInitiatorsMap.get(hostURI);
            // Find the ExportMask for my host.
            List<ExportMask> exportMasks = getExportMaskForHost(exportGroup, hostURI, vplexURI);
            if (exportMasks == null || exportMasks.isEmpty()) {
                // If there is no ExportMask for this host, there is nothing to do.
                _log.info("No export mask found for hostURI: " + hostURI);
                continue;
            }
            String lastStep = null;
            List<URI> initiatorsAlreadyRemovedFromExportGroup = new ArrayList<URI>();
            for (ExportMask exportMask : exportMasks) {
                _log.info("adding remove initiators steps for " + "export mask / storage view: " + exportMask.getMaskName());
                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);
                // initiator filter logic is move inside addStepsForRemoveInitiators and addStepsForInitiatorRemoval as
                // it is not required for zone related operation.
                // 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(opId));
                validator.removeInitiators(ctx).validate();
                lastStep = addStepsForRemoveInitiators(vplex, workflow, completer, exportGroup, exportMask, initiators, hostURI, initiatorsAlreadyRemovedFromExportGroup, errorMessages, lastStep);
                if (lastStep != null) {
                    hasStep = true;
                }
            }
        }
        String message = errorMessages.toString();
        if (isValidationNeeded && !message.isEmpty()) {
            _log.error("Error Message {}", errorMessages);
            List<String> initiatorNames = new ArrayList<String>();
            for (URI initiatorURI : initiatorURIs) {
                Initiator initiator = _dbClient.queryObject(Initiator.class, initiatorURI);
                if (initiator != null) {
                    String normalizedName = Initiator.normalizePort(initiator.getInitiatorPort());
                    initiatorNames.add(normalizedName);
                } else {
                    _log.warn("no initiator found for URI {}", initiatorURI);
                }
            }
            throw DeviceControllerException.exceptions.removeInitiatorValidationError(Joiner.on(", ").join(initiatorNames), vplex.getLabel(), message);
        }
        // Fire off the workflow if there were initiators to delete. Otherwise just fire completer.
        if (hasStep) {
            workflow.executePlan(completer, "Successfully removed initiators: " + initiatorURIs.toString());
        } else {
            _log.info(String.format("No updates to ExportMasks needed... complete"));
            completer.ready(_dbClient);
        }
    } catch (VPlexApiException vae) {
        _log.error("Exception in exportRemoveInitiators: " + initiatorURIs.toString(), vae);
        WorkflowStepCompleter.stepFailed(opId, vae);
    } catch (Exception ex) {
        _log.error("Exception in exportRemoveInitiators: " + initiatorURIs.toString(), ex);
        String opName = ResourceOperationTypeEnum.DELETE_EXPORT_INITIATOR.getName();
        ServiceError serviceError = VPlexApiException.errors.exportGroupRemoveInitiatorsFailed(opName, ex);
        WorkflowStepCompleter.stepFailed(opId, serviceError);
    }
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) ExportRemoveInitiatorCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportRemoveInitiatorCompleter) ArrayList(java.util.ArrayList) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) Initiator(com.emc.storageos.db.client.model.Initiator) ApplicationAddVolumeList(com.emc.storageos.volumecontroller.ApplicationAddVolumeList) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) List(java.util.List) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ExportMask(com.emc.storageos.db.client.model.ExportMask) 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) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) ExportMaskValidationContext(com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient)

Example 9 with ExportMaskValidationContext

use of com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext in project coprhd-controller by CoprHD.

the class XtremIOExportOperations method removeInitiators.

@Override
public void removeInitiators(StorageSystem storage, URI exportMaskURI, List<URI> volumeURIList, List<Initiator> initiators, List<URI> targets, TaskCompleter taskCompleter) throws DeviceControllerException {
    _log.info("{} removeInitiators START...", storage.getSerialNumber());
    boolean isRollback = WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId());
    if (isRollback) {
        _log.info("Handling removeInitiators as a result of rollback");
        List<Initiator> addedInitiators = new ArrayList<Initiator>();
        // Get the context from the task completer.
        ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
        if (context != null && context.getOperations() != null) {
            ListIterator li = context.getOperations().listIterator(context.getOperations().size());
            while (li.hasPrevious()) {
                ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
                if (operation != null && XtremIOExportOperationContext.OPERATION_ADD_INITIATORS_TO_INITIATOR_GROUP.equals(operation.getOperation())) {
                    addedInitiators = (List<Initiator>) 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 (Initiator initiator : initiators) {
            if (addedInitiators == null || !addedInitiators.contains(initiator)) {
                ((ExportMaskRemoveInitiatorCompleter) taskCompleter).removeInitiator(initiator.getId());
            }
        }
        initiators = addedInitiators;
        if (initiators == null || initiators.isEmpty()) {
            _log.info("There was no context found for add initiator. So there is nothing to rollback.");
            taskCompleter.ready(dbClient);
            return;
        }
    }
    ExportMask exportMask = dbClient.queryObject(ExportMask.class, exportMaskURI);
    if (exportMask == null || exportMask.getInactive()) {
        throw new DeviceControllerException("Invalid ExportMask URI: " + exportMaskURI);
    }
    XtremIOClient client = null;
    // if host Name is not available in at least one of the initiator, then set it to
    // Default_IG;
    List<String> failedIGs = new ArrayList<String>();
    ArrayListMultimap<String, Initiator> groupInitiatorsByIG = ArrayListMultimap.create();
    try {
        String hostName = null;
        String clusterName = null;
        client = XtremIOProvUtils.getXtremIOClient(dbClient, storage, xtremioRestClientFactory);
        String xioClusterName = client.getClusterDetails(storage.getSerialNumber()).getName();
        Iterator<Initiator> iniItr = initiators.iterator();
        while (iniItr.hasNext()) {
            Initiator initiator = iniItr.next();
            String igName = null;
            if (null != initiator.getHostName()) {
                // initiators already grouped by Host
                hostName = initiator.getHostName();
                clusterName = initiator.getClusterName();
            }
            igName = XtremIOProvUtils.getIGNameForInitiator(initiator, storage.getSerialNumber(), client, xioClusterName);
            if (igName != null && !igName.isEmpty()) {
                groupInitiatorsByIG.put(igName, initiator);
            } else {
                // initiator not found in Array, remove from DB
                exportMask.removeFromExistingInitiators(initiator);
                exportMask.removeFromUserCreatedInitiators(initiator);
                iniItr.remove();
            }
        }
        // We need to look at all related initiators from the affected EM. We can use this list
        // to then find all related volumes across all EMs. This will allow us to properly
        // perform our validations.
        List<Initiator> relatedInitiators = new ArrayList<Initiator>();
        if (exportMask.getInitiators() != null && !exportMask.getInitiators().isEmpty()) {
            Collection<URI> relatedInitiatorURIs = Collections2.transform(exportMask.getInitiators(), CommonTransformerFunctions.FCTN_STRING_TO_URI);
            relatedInitiators.addAll(dbClient.queryObject(Initiator.class, relatedInitiatorURIs));
        } else {
            relatedInitiators.addAll(initiators);
        }
        Set<URI> allRelatedVolumes = new HashSet<URI>();
        allRelatedVolumes.addAll(findAllRelatedExportMaskVolumesForInitiator(relatedInitiators, exportMask.getStorageDevice()));
        _log.info("removeInitiators: Export mask id: {}", exportMaskURI);
        if (!CollectionUtils.isEmpty(allRelatedVolumes)) {
            _log.info("removeInitiators: volumes : {}", Joiner.on(',').join(allRelatedVolumes));
        }
        _log.info("removeInitiators: initiators : {}", Joiner.on(',').join(initiators));
        _log.info("removeInitiators: targets : {}", Joiner.on(',').join(targets));
        _log.info("List of  IGs found {} with size : {}", Joiner.on(",").join(groupInitiatorsByIG.asMap().entrySet()), groupInitiatorsByIG.size());
        ExportMaskValidationContext ctx = new ExportMaskValidationContext();
        ctx.setStorage(storage);
        ctx.setExportMask(exportMask);
        ctx.setBlockObjects(allRelatedVolumes, dbClient);
        ctx.setAllowExceptions(!isRollback);
        XtremIOExportMaskVolumesValidator volumeValidator = (XtremIOExportMaskVolumesValidator) validator.removeInitiators(ctx);
        volumeValidator.setIgNames(groupInitiatorsByIG.keySet());
        volumeValidator.validate();
        // lun map
        for (Initiator initiator : initiators) {
            try {
                client.deleteInitiator(initiator.getMappedInitiatorName(storage.getSerialNumber()), xioClusterName);
                exportMask.removeFromExistingInitiators(initiator);
                exportMask.removeFromUserCreatedInitiators(initiator);
            } catch (Exception e) {
                failedIGs.add(initiator.getLabel().concat(XtremIOConstants.DASH).concat(e.getMessage()));
                _log.warn("Removal of Initiator {} failed", initiator.getLabel(), e);
            }
        }
        dbClient.updateObject(exportMask);
        if (!failedIGs.isEmpty()) {
            String errMsg = "Export Operations failed deleting these initiators: ".concat(Joiner.on(", ").join(failedIGs));
            ServiceError serviceError = DeviceControllerException.errors.jobFailedMsg(errMsg, null);
            taskCompleter.error(dbClient, serviceError);
            return;
        }
        // Clean IGs if empty
        deleteInitiatorGroup(groupInitiatorsByIG, client, xioClusterName);
        // delete IG Folder as well if IGs are empty
        deleteInitiatorGroupFolder(client, xioClusterName, clusterName, hostName, storage);
        taskCompleter.ready(dbClient);
    } catch (Exception ex) {
        _log.error("Problem in removeInitiators: ", ex);
        ServiceError serviceError = DeviceControllerErrors.xtremio.operationFailed("removeInitiators", ex.getMessage());
        taskCompleter.error(dbClient, serviceError);
        return;
    }
    _log.info("{} removeInitiators END...", storage.getSerialNumber());
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) XtremIOExportMaskVolumesValidator(com.emc.storageos.volumecontroller.impl.validators.xtremio.XtremIOExportMaskVolumesValidator) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) ListIterator(java.util.ListIterator) ExportMaskRemoveInitiatorCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskRemoveInitiatorCompleter) URI(java.net.URI) XtremIOApiException(com.emc.storageos.xtremio.restapi.errorhandling.XtremIOApiException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) ExportMaskValidationContext(com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext) XtremIOInitiator(com.emc.storageos.xtremio.restapi.model.response.XtremIOInitiator) Initiator(com.emc.storageos.db.client.model.Initiator) ExportOperationContext(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext) XtremIOClient(com.emc.storageos.xtremio.restapi.XtremIOClient) ExportOperationContextOperation(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) HashSet(java.util.HashSet)

Example 10 with ExportMaskValidationContext

use of com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext in project coprhd-controller by CoprHD.

the class XtremIOExportOperations method runLunMapDeletionOrRemoveInitiatorAlgorithm.

/**
 * It deletes the LunMap if the IG contains no other initiators than the requested ones.
 * Else it removes the requested initiators from the IG
 */
private void runLunMapDeletionOrRemoveInitiatorAlgorithm(StorageSystem storage, ExportMask exportMask, List<URI> volumes, List<Initiator> initiators, TaskCompleter taskCompleter) throws DeviceControllerException {
    // find LunMap associated with Volume
    // Then find initiatorGroup associated with this lun map
    XtremIOClient client = null;
    // Default_IG;
    try {
        String hostName = null;
        String clusterName = null;
        client = XtremIOProvUtils.getXtremIOClient(dbClient, storage, xtremioRestClientFactory);
        String xioClusterName = client.getClusterDetails(storage.getSerialNumber()).getName();
        boolean initiatorsOfRP = ExportUtils.checkIfInitiatorsForRP(initiators);
        for (Initiator initiator : initiators) {
            if (null != initiator.getHostName()) {
                // initiators already grouped by Host
                hostName = initiator.getHostName();
                clusterName = initiator.getClusterName();
                break;
            }
        }
        ArrayListMultimap<String, Initiator> groupInitiatorsByIG = XtremIOProvUtils.mapInitiatorToInitiatorGroup(storage.getSerialNumber(), initiators, null, xioClusterName, client);
        ArrayListMultimap<String, Initiator> knownInitiatorsToIGMap = ArrayListMultimap.create();
        // DU validations for removing volumes from IG.
        ExportMaskValidationContext ctx = new ExportMaskValidationContext();
        ctx.setStorage(storage);
        ctx.setExportMask(exportMask);
        ctx.setInitiators(initiators);
        ctx.setAllowExceptions(!WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId()));
        XtremIOExportMaskInitiatorsValidator initiatorsValidator = (XtremIOExportMaskInitiatorsValidator) validator.removeVolumes(ctx);
        initiatorsValidator.setInitiatorToIGMap(groupInitiatorsByIG);
        initiatorsValidator.setKnownInitiatorToIGMap(knownInitiatorsToIGMap);
        initiatorsValidator.validate();
        Set<String> igNames = groupInitiatorsByIG.keySet();
        List<String> failedVolumes = new ArrayList<String>();
        List<String> failedIGs = new ArrayList<String>();
        for (URI volumeUri : volumes) {
            BlockObject blockObj = BlockObject.fetch(dbClient, volumeUri);
            _log.info("Block Obj {} , wwn {}", blockObj.getId(), blockObj.getWWN());
            XtremIOVolume xtremIOVolume = null;
            if (URIUtil.isType(volumeUri, Volume.class)) {
                xtremIOVolume = XtremIOProvUtils.isVolumeAvailableInArray(client, blockObj.getDeviceLabel(), xioClusterName);
            } else {
                if (URIUtil.isType(volumeUri, BlockSnapshot.class) && BlockObject.checkForRP(dbClient, volumeUri)) {
                    // If the BlockObject is a BlockSnapshot of type RP (bookmark), there will be no exported
                    // snapshot. In this case, a target volume will have been exported and the deviceLabel of
                    // the BlockSnapshot reflects the name of that target.
                    _log.info(String.format("Dealing with a RecoverPoint bookmark lun mapping.  Checking to see if volume %s is available on array.", blockObj.getDeviceLabel()));
                    xtremIOVolume = XtremIOProvUtils.isVolumeAvailableInArray(client, blockObj.getDeviceLabel(), xioClusterName);
                } else {
                    xtremIOVolume = XtremIOProvUtils.isSnapAvailableInArray(client, blockObj.getDeviceLabel(), xioClusterName);
                }
            }
            if (null != xtremIOVolume) {
                // I need lun map id and igName
                // if iGName is available in the above group:
                _log.info("Volume Details {}", xtremIOVolume.toString());
                _log.info("Volume lunMap details {}", xtremIOVolume.getLunMaps().toString());
                // Lun Maps to delete
                Set<String> lunMaps = new HashSet<String>();
                boolean removeInitiator = false;
                String volId = xtremIOVolume.getVolInfo().get(2);
                if (xtremIOVolume.getLunMaps().isEmpty()) {
                    // handle scenarios where volumes gets unexported already
                    _log.info("Volume  {} doesn't have any existing export available on Array, unexported already.", xtremIOVolume.toString());
                    exportMask.removeFromUserCreatedVolumes(blockObj);
                    exportMask.removeVolume(blockObj.getId());
                    continue;
                }
                for (List<Object> lunMapEntries : xtremIOVolume.getLunMaps()) {
                    @SuppressWarnings("unchecked") List<Object> igDetails = (List<Object>) lunMapEntries.get(0);
                    String igName = (String) igDetails.get(1);
                    // IG details is actually transforming to a double by default, even though
                    // its modeled as List<String>
                    // hence this logic
                    Double IgIdDouble = (Double) igDetails.get(2);
                    String igId = String.valueOf(IgIdDouble.intValue());
                    _log.info("IG Name: {} Id: {} found in Lun Map", igName, igId);
                    if (!igNames.contains(igName)) {
                        _log.info("Volume is associated with IG {} which is not in the removal list requested, ignoring..", igName);
                        continue;
                    }
                    /**
                     * i) If Cluster export:
                     * If there are additional initiators other than the requested ones (Single IG with all cluster
                     * initiators)
                     * - - - remove initiator from IG,
                     * - - - Note: If initiators are of RP (CTRL-13622), always delete LunMap.
                     * - ii) Host export:
                     * - - -- delete LunMap
                     */
                    boolean igHasOtherHostInitiatorsOfSameCluster = knownInitiatorsToIGMap.get(igName).size() > groupInitiatorsByIG.get(igName).size();
                    if (!initiatorsOfRP && clusterName != null && igHasOtherHostInitiatorsOfSameCluster) {
                        removeInitiator = true;
                    }
                    if (!removeInitiator) {
                        // delete LunMap
                        @SuppressWarnings("unchecked") List<Object> tgtGroupDetails = (List<Object>) lunMapEntries.get(1);
                        Double tgIdDouble = (Double) tgtGroupDetails.get(2);
                        String tgtid = String.valueOf(tgIdDouble.intValue());
                        String lunMapId = volId.concat(XtremIOConstants.UNDERSCORE).concat(igId).concat(XtremIOConstants.UNDERSCORE).concat(tgtid);
                        _log.info("LunMap Id {} Found associated with Volume {}", lunMapId, blockObj.getDeviceLabel());
                        lunMaps.add(lunMapId);
                    }
                }
                // there will be only one lun map always
                for (String lunMap : lunMaps) {
                    try {
                        client.deleteLunMap(lunMap, xioClusterName);
                    } catch (Exception e) {
                        failedVolumes.add(volumeUri.toString().concat(XtremIOConstants.DASH).concat(e.getMessage()));
                        _log.warn("Deletion of Lun Map {} failed}", lunMap, e);
                    }
                }
                // remove initiator from IG
                if (removeInitiator) {
                    _log.info("Removing requested intiators from IG instead of deleting LunMap" + " as the IG contains other Host's initiators belonging to same Cluster.");
                    ctx = new ExportMaskValidationContext();
                    ctx.setStorage(storage);
                    ctx.setExportMask(exportMask);
                    ctx.setBlockObjects(volumes, dbClient);
                    ctx.setAllowExceptions(!WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId()));
                    // DU validation when removing initiators
                    XtremIOExportMaskVolumesValidator volumeValidator = (XtremIOExportMaskVolumesValidator) validator.removeInitiators(ctx);
                    volumeValidator.setIgNames(groupInitiatorsByIG.keySet());
                    volumeValidator.validate();
                    List<Initiator> initiatorsToBeRemoved = new ArrayList<Initiator>();
                    // Get the context from the task completer, in case this is a rollback.
                    ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
                    if (context != null && context.getOperations() != null) {
                        ListIterator li = context.getOperations().listIterator(context.getOperations().size());
                        while (li.hasPrevious()) {
                            _log.info("Handling deleteExportMask as a result of rollback");
                            ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
                            if (operation != null && XtremIOExportOperationContext.OPERATION_ADD_INITIATORS_TO_INITIATOR_GROUP.equals(operation.getOperation())) {
                                initiatorsToBeRemoved = (List<Initiator>) operation.getArgs().get(0);
                                _log.info("Removing initiators {} as part of rollback", Joiner.on(',').join(initiatorsToBeRemoved));
                            }
                        }
                    } else {
                        initiatorsToBeRemoved = initiators;
                    }
                    // Deleting the initiator automatically removes the initiator from lun map
                    for (Initiator initiator : initiatorsToBeRemoved) {
                        try {
                            // check if Initiator has already been deleted during previous volume processing
                            String initiatorName = initiator.getMappedInitiatorName(storage.getSerialNumber());
                            XtremIOInitiator initiatorObj = client.getInitiator(initiatorName, xioClusterName);
                            if (null != initiatorObj) {
                                client.deleteInitiator(initiatorName, xioClusterName);
                            } else {
                                _log.info("Initiator {} already deleted", initiatorName);
                            }
                        } catch (Exception e) {
                            failedIGs.add(initiator.getLabel().concat(XtremIOConstants.DASH).concat(e.getMessage()));
                            _log.warn("Removal of Initiator {} from IG failed", initiator.getLabel(), e);
                        }
                    }
                }
            } else {
                exportMask.removeFromUserCreatedVolumes(blockObj);
                exportMask.removeVolume(blockObj.getId());
            }
        }
        dbClient.updateObject(exportMask);
        if (!failedVolumes.isEmpty()) {
            String errMsg = "Export Operations failed for these volumes: ".concat(Joiner.on(", ").join(failedVolumes));
            ServiceError serviceError = DeviceControllerException.errors.jobFailedMsg(errMsg, null);
            taskCompleter.error(dbClient, serviceError);
            return;
        }
        if (!failedIGs.isEmpty()) {
            String errMsg = "Export Operations failed deleting these initiators: ".concat(Joiner.on(", ").join(failedIGs));
            ServiceError serviceError = DeviceControllerException.errors.jobFailedMsg(errMsg, null);
            taskCompleter.error(dbClient, serviceError);
            return;
        }
        // Clean IGs if empty
        deleteInitiatorGroup(groupInitiatorsByIG, client, xioClusterName);
        // delete IG Folder as well if IGs are empty
        deleteInitiatorGroupFolder(client, xioClusterName, clusterName, hostName, storage);
        taskCompleter.ready(dbClient);
    } catch (Exception e) {
        _log.error(String.format("Export Operations failed - maskName: %s", exportMask.getId().toString()), e);
        ServiceError serviceError = DeviceControllerException.errors.jobFailed(e);
        taskCompleter.error(dbClient, serviceError);
    }
}
Also used : XtremIOExportMaskInitiatorsValidator(com.emc.storageos.volumecontroller.impl.validators.xtremio.XtremIOExportMaskInitiatorsValidator) ArrayList(java.util.ArrayList) URI(java.net.URI) XtremIOInitiator(com.emc.storageos.xtremio.restapi.model.response.XtremIOInitiator) XtremIOVolume(com.emc.storageos.xtremio.restapi.model.response.XtremIOVolume) XtremIOInitiator(com.emc.storageos.xtremio.restapi.model.response.XtremIOInitiator) Initiator(com.emc.storageos.db.client.model.Initiator) ExportOperationContext(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext) List(java.util.List) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) ExportOperationContextOperation(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation) BlockObject(com.emc.storageos.db.client.model.BlockObject) HashSet(java.util.HashSet) ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) XtremIOExportMaskVolumesValidator(com.emc.storageos.volumecontroller.impl.validators.xtremio.XtremIOExportMaskVolumesValidator) BlockSnapshot(com.emc.storageos.db.client.model.BlockSnapshot) ListIterator(java.util.ListIterator) XtremIOApiException(com.emc.storageos.xtremio.restapi.errorhandling.XtremIOApiException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) ExportMaskValidationContext(com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext) XtremIOClient(com.emc.storageos.xtremio.restapi.XtremIOClient) BlockObject(com.emc.storageos.db.client.model.BlockObject)

Aggregations

ExportMaskValidationContext (com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext)20 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)19 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)19 ArrayList (java.util.ArrayList)19 ExportMask (com.emc.storageos.db.client.model.ExportMask)17 URI (java.net.URI)15 Initiator (com.emc.storageos.db.client.model.Initiator)13 ExportOperationContext (com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext)13 ExportOperationContextOperation (com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation)10 HashSet (java.util.HashSet)9 ListIterator (java.util.ListIterator)8 BlockObject (com.emc.storageos.db.client.model.BlockObject)6 SmisException (com.emc.storageos.volumecontroller.impl.smis.SmisException)6 WBEMException (javax.wbem.WBEMException)6 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)5 NamedURI (com.emc.storageos.db.client.model.NamedURI)5 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)5 List (java.util.List)5 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)4 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)4