Search in sources :

Example 26 with WorkflowException

use of com.emc.storageos.workflow.WorkflowException in project coprhd-controller by CoprHD.

the class VPlexDeviceController method deleteMirrorDevice.

/**
 * Do the delete of a VPlex mirror device .
 * This is called as a Workflow Step.
 * NOTE: The parameters here must match deleteMirrorDeviceMethod above (except stepId).
 *
 * @param vplexURI
 *            URI of the VPlex StorageSystem
 * @param vplexMirrorURI
 *            URI of the mirror to be deleted
 * @param stepId
 *            The stepId used for completion.
 *
 * @throws WorkflowException
 *             When an error occurs updating the workflow step
 *             state.
 */
public void deleteMirrorDevice(URI vplexURI, URI vplexMirrorURI, String stepId) throws WorkflowException {
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexURI, _dbClient);
        VplexMirror vplexMirror = getDataObject(VplexMirror.class, vplexMirrorURI, _dbClient);
        if (vplexMirror.getDeviceLabel() != null) {
            // Call to delete mirror device
            client.deleteLocalDevice(vplexMirror.getDeviceLabel());
            if (vplexMirror.getSource() != null && vplexMirror.getSource().getURI() != null) {
                Volume vplexVolume = getDataObject(Volume.class, vplexMirror.getSource().getURI(), _dbClient);
                StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
                updateThinProperty(client, vplexSystem, vplexVolume);
            }
            // Record VPLEX mirror delete event.
            recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.DELETE_VOLUME_MIRROR.getEvType(true), Operation.Status.ready, OperationTypeEnum.DELETE_VOLUME_MIRROR.getDescription());
        } else {
            _log.info("It seems vplex mirror {} was never created, so just move to the next step.", vplexMirror.getLabel());
        }
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (VPlexApiException vae) {
        _log.error("Exception deleting VPlex Virtual Volume: " + vae.getMessage(), vae);
        recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.DELETE_VOLUME_MIRROR.getEvType(true), Operation.Status.error, OperationTypeEnum.DELETE_VOLUME_MIRROR.getDescription());
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception deleting VPlex Virtual Volume: " + ex.getMessage(), ex);
        String opName = ResourceOperationTypeEnum.DELETE_VPLEX_LOCAL_MIRROR.getName();
        ServiceError serviceError = VPlexApiException.errors.deleteMirrorFailed(opName, ex);
        recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.DELETE_VOLUME_MIRROR.getEvType(true), Operation.Status.error, OperationTypeEnum.DELETE_VOLUME_MIRROR.getDescription());
        WorkflowStepCompleter.stepFailed(stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) Volume(com.emc.storageos.db.client.model.Volume) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) VplexMirror(com.emc.storageos.db.client.model.VplexMirror) 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) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 27 with WorkflowException

use of com.emc.storageos.workflow.WorkflowException in project coprhd-controller by CoprHD.

the class VPlexDeviceController method deleteMigrationSources.

/**
 * This step is executed after a virtual volume is successfully migrated to
 * delete the old source volumes. We create a sub workflow to perform this
 * task. We do this in a sub workflow because we don't want any of the steps
 * required to delete the sources to initiate rollback in the main workflow
 * if it fails.
 *
 * We also update the class of service, if required, for the virtual
 * volume when the migration is the result of a CoS change. When this
 * step is executed we know that the migrations have been committed and
 * the new CoS now applies to the virtual volume.
 *
 * @param vplexURI
 *            The URI of the VPlex storage system.
 * @param virtualVolumeURI
 *            The URI of the virtual volume.
 * @param newVpoolURI
 *            The CoS to be assigned to the virtual volume
 *            upon successful commit of the migration or null when not
 *            specified.
 * @param newVarrayURI
 *            The varray to be assigned to the virtual volume
 *            upon successful commit of the migration or null when not
 *            specified.
 * @param migrationSources
 *            The migration sources to delete.
 * @param stepId
 *            The workflow step id.
 * @throws WorkflowException
 */
public void deleteMigrationSources(URI vplexURI, URI virtualVolumeURI, URI newVpoolURI, URI newVarrayURI, List<URI> migrationSources, String stepId) throws WorkflowException {
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        // First update the virtual volume CoS, if necessary.
        Volume volume = _dbClient.queryObject(Volume.class, virtualVolumeURI);
        // or create a new exportGroup
        if (newVarrayURI != null && volume.isVolumeExported(_dbClient)) {
            URIQueryResultList exportGroupURIs = new URIQueryResultList();
            _dbClient.queryByConstraint(ContainmentConstraint.Factory.getBlockObjectExportGroupConstraint(virtualVolumeURI), exportGroupURIs);
            Iterator<URI> iterator = exportGroupURIs.iterator();
            while (iterator.hasNext()) {
                URI egUri = iterator.next();
                ExportGroup eg = _dbClient.queryObject(ExportGroup.class, egUri);
                if (eg != null) {
                    StringMap volumesMap = eg.getVolumes();
                    String lun = volumesMap.get(virtualVolumeURI.toString());
                    if (lun == null || lun.isEmpty()) {
                        lun = ExportGroup.LUN_UNASSIGNED_DECIMAL_STR;
                    }
                    List<URI> initiators = StringSetUtil.stringSetToUriList(eg.getInitiators());
                    ExportGroup newEg = null;
                    if (initiators != null && !initiators.isEmpty()) {
                        URI initiatorUri = initiators.get(0);
                        AlternateIdConstraint constraint = AlternateIdConstraint.Factory.getExportGroupInitiatorConstraint(initiatorUri.toString());
                        URIQueryResultList egUris = new URIQueryResultList();
                        _dbClient.queryByConstraint(constraint, egUris);
                        Iterator<URI> egIt = egUris.iterator();
                        while (egIt.hasNext()) {
                            ExportGroup theEg = _dbClient.queryObject(ExportGroup.class, egIt.next());
                            if (theEg.getVirtualArray().equals(newVarrayURI)) {
                                List<URI> theEgInits = StringSetUtil.stringSetToUriList(theEg.getInitiators());
                                if (theEgInits.containsAll(initiators) && theEgInits.size() == initiators.size()) {
                                    _log.info(String.format("Found existing exportGroup %s", theEg.getId().toString()));
                                    newEg = theEg;
                                    break;
                                }
                            }
                        }
                    }
                    if (newEg != null) {
                        // add the volume to the export group
                        newEg.addVolume(virtualVolumeURI, Integer.valueOf(lun));
                        _dbClient.updateObject(newEg);
                    } else {
                        // create a new export group
                        _log.info("Creating new ExportGroup");
                        createExportGroup(eg, volume, Integer.valueOf(lun));
                    }
                    eg.removeVolume(virtualVolumeURI);
                    _dbClient.updateObject(eg);
                }
            }
        }
        if (!migrationSources.isEmpty()) {
            final String workflowKey = "deleteOriginalSources";
            if (!WorkflowService.getInstance().hasWorkflowBeenCreated(stepId, workflowKey)) {
                // Now create and execute the sub workflow to delete the
                // migration source volumes if we have any. If the volume
                // migrated was ingested VPLEX volume we will not have
                // the sources.
                String subTaskId = stepId;
                Workflow subWorkflow = _workflowService.getNewWorkflow(this, DELETE_MIGRATION_SOURCES_WF_NAME, true, subTaskId);
                WorkflowTaskCompleter completer = new WorkflowTaskCompleter(subWorkflow.getWorkflowURI(), subTaskId);
                // Creates steps to remove the migration source volumes from all
                // export groups containing them and delete them.
                boolean unexportStepsAdded = vplexAddUnexportVolumeWfSteps(subWorkflow, null, migrationSources, null);
                // Only need to wait for unexport if there was a step for it added
                // to the workflow.
                String waitFor = null;
                if (unexportStepsAdded) {
                    waitFor = UNEXPORT_STEP;
                    // If the migration sources are unexported, Add a step to
                    // forget these backend volumes.
                    addStepToForgetVolumes(subWorkflow, vplexURI, migrationSources, waitFor);
                }
                // Add steps to delete the volumes.
                Iterator<URI> migrationSourcesIter = migrationSources.iterator();
                while (migrationSourcesIter.hasNext()) {
                    URI migrationSourceURI = migrationSourcesIter.next();
                    _log.info("Migration source URI is {}", migrationSourceURI);
                    Volume migrationSource = _dbClient.queryObject(Volume.class, migrationSourceURI);
                    URI sourceSystemURI = migrationSource.getStorageController();
                    _log.info("Source storage system URI is {}", sourceSystemURI);
                    StorageSystem sourceSystem = _dbClient.queryObject(StorageSystem.class, sourceSystemURI);
                    String subWFStepId = subWorkflow.createStepId();
                    Workflow.Method deleteVolumesMethod = new Workflow.Method(DELETE_VOLUMES_METHOD_NAME, sourceSystemURI, Arrays.asList(migrationSourceURI));
                    _log.info("Creating workflow step to delete source");
                    subWorkflow.createStep(MIGRATION_VOLUME_DELETE_STEP, String.format("Delete volume from storage system: %s", sourceSystemURI), waitFor, sourceSystemURI, sourceSystem.getSystemType(), BlockDeviceController.class, deleteVolumesMethod, null, subWFStepId);
                    _log.info("Created workflow step to delete source");
                }
                // Execute this sub workflow.
                subWorkflow.executePlan(completer, "Deleted migration sources");
                // Mark this workflow as created/executed so we don't do it again on retry/resume
                WorkflowService.getInstance().markWorkflowBeenCreated(stepId, workflowKey);
            }
        } else {
            // No sources to delete. Must have migrated an ingested volume.
            WorkflowStepCompleter.stepSucceded(stepId);
            _log.info("Updated workflow step to success");
        }
    } catch (Exception ex) {
        // Log the error.
        _log.error("Error deleting migration sources", ex);
        // Always return success. This is a cleanup step after a
        // successfully committed migration. We don't want rollback,
        // so we return success.
        WorkflowStepCompleter.stepSucceded(stepId);
    }
}
Also used : StringMap(com.emc.storageos.db.client.model.StringMap) Workflow(com.emc.storageos.workflow.Workflow) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) AlternateIdConstraint(com.emc.storageos.db.client.constraint.AlternateIdConstraint) 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) Volume(com.emc.storageos.db.client.model.Volume) WorkflowTaskCompleter(com.emc.storageos.workflow.WorkflowTaskCompleter) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 28 with WorkflowException

use of com.emc.storageos.workflow.WorkflowException in project coprhd-controller by CoprHD.

the class VPlexDeviceController method rollbackCreateVirtualVolumes.

/**
 * Rollback any virtual volumes previously created.
 *
 * @param vplexURI
 * @param vplexVolumeURIs
 * @param executeStepId
 *            - step Id of the execute step; used to retrieve rollback data.
 * @param stepId
 * @throws WorkflowException
 */
public void rollbackCreateVirtualVolumes(URI vplexURI, List<URI> vplexVolumeURIs, String executeStepId, String stepId) throws WorkflowException {
    try {
        List<List<VolumeInfo>> rollbackData = (List<List<VolumeInfo>>) _workflowService.loadStepData(executeStepId);
        if (rollbackData != null) {
            WorkflowStepCompleter.stepExecuting(stepId);
            // Get the API client.
            StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
            VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
            // For each virtual volume attempted, try and rollback.
            for (List<VolumeInfo> rollbackList : rollbackData) {
                client.deleteVirtualVolume(rollbackList);
            }
        }
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (VPlexApiException vae) {
        _log.error("Exception rollback VPlex Virtual Volume create: " + vae.getLocalizedMessage(), vae);
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception rollback VPlex Virtual Volume create: " + ex.getLocalizedMessage(), ex);
        ServiceError serviceError = VPlexApiException.errors.createVirtualVolumesRollbackFailed(stepId, ex);
        WorkflowStepCompleter.stepFailed(stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) ApplicationAddVolumeList(com.emc.storageos.volumecontroller.ApplicationAddVolumeList) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) List(java.util.List) VolumeInfo(com.emc.storageos.vplex.api.clientdata.VolumeInfo) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) 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) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 29 with WorkflowException

use of com.emc.storageos.workflow.WorkflowException in project coprhd-controller by CoprHD.

the class VPlexDeviceController method storageViewRemoveVolumes.

/**
 * @param client
 *            -- VPlexApiClient used for communication
 * @param exportGroupURI
 *            -- Export Group
 * @param exportMaskURI
 *            -- ExportMask corresponding to the StorageView
 * @param volumeURIList
 *            -- URI of virtual volumes
 * @param parentStepId
 *            -- Workflow parent step id
 * @param taskCompleter
 *            -- the task completer, used to find the rollback context,
 *               which will be non-null in the case of rollback
 * @param rollbackContextKey
 *            context key for rollback processing
 * @param stepId
 *            -- Workflow step id
 * @throws WorkflowException
 */
public void storageViewRemoveVolumes(URI vplexURI, URI exportGroupURI, URI exportMaskURI, List<URI> volumeURIList, String parentStepId, TaskCompleter taskCompleter, String rollbackContextKey, String stepId) throws WorkflowException {
    ExportMaskRemoveVolumeCompleter completer = null;
    ExportGroup exportGroup = null;
    ExportMask exportMask = null;
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        List<URI> volumeIdsToProcess = new ArrayList<>(volumeURIList);
        exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
        exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
        completer = new ExportMaskRemoveVolumeCompleter(exportGroup.getId(), exportMask.getId(), volumeURIList, stepId);
        // get the context from the task completer, in case this is a rollback.
        if (taskCompleter != null && rollbackContextKey != null) {
            ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(rollbackContextKey);
            if (context != null) {
                // a non-null context means this step is running as part of a rollback.
                List<URI> addedVolumes = new ArrayList<>();
                if (context.getOperations() != null) {
                    _log.info("Handling removeVolumes as a result of rollback");
                    ListIterator<ExportOperationContextOperation> li = context.getOperations().listIterator(context.getOperations().size());
                    while (li.hasPrevious()) {
                        ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
                        if (operation != null && VplexExportOperationContext.OPERATION_ADD_VOLUMES_TO_STORAGE_VIEW.equals(operation.getOperation())) {
                            addedVolumes = (List<URI>) operation.getArgs().get(0);
                            _log.info("Removing volumes {} as part of rollback", Joiner.on(',').join(addedVolumes));
                        }
                    }
                    if (addedVolumes == null || addedVolumes.isEmpty()) {
                        _log.info("There was no context found for add volumes. So there is nothing to rollback.");
                        completer.ready(_dbClient);
                        return;
                    }
                }
                // change the list of initiators to process to the
                // list that successfully were added during addInitiators.
                volumeIdsToProcess.clear();
                volumeIdsToProcess.addAll(addedVolumes);
            }
        }
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        // Removes the specified volumes from the storage view
        // and updates the export mask.
        removeVolumesFromStorageViewAndMask(client, exportMask, volumeIdsToProcess, parentStepId);
        completer.ready(_dbClient);
    } catch (VPlexApiException vae) {
        _log.error("Exception removing volumes from Storage View: " + vae.getMessage(), vae);
        failStep(completer, stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception removing volumes from Storage View: " + ex.getMessage(), ex);
        String opName = ResourceOperationTypeEnum.REMOVE_STORAGE_VIEW_VOLUME.getName();
        ServiceError serviceError = VPlexApiException.errors.storageViewRemoveVolumeFailed(exportMask != null ? exportMask.getMaskName() : "none", opName, ex);
        failStep(completer, stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) 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) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) 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) ExportMaskRemoveVolumeCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskRemoveVolumeCompleter) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 30 with WorkflowException

use of com.emc.storageos.workflow.WorkflowException 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)

Aggregations

WorkflowException (com.emc.storageos.workflow.WorkflowException)38 ControllerException (com.emc.storageos.volumecontroller.ControllerException)36 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)34 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)34 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)34 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)31 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)31 VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)29 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)27 IOException (java.io.IOException)27 URISyntaxException (java.net.URISyntaxException)27 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)26 Volume (com.emc.storageos.db.client.model.Volume)24 URI (java.net.URI)21 ArrayList (java.util.ArrayList)18 NamedURI (com.emc.storageos.db.client.model.NamedURI)16 VPlexVirtualVolumeInfo (com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo)10 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)8 VplexMirror (com.emc.storageos.db.client.model.VplexMirror)8 ExportMask (com.emc.storageos.db.client.model.ExportMask)7