Search in sources :

Example 31 with VPlexApiException

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

the class VPlexDeviceController method rollbackMigrateVirtualVolume.

/**
 * Called when a migration cannot be created and started or the data
 * migration is terminated prior to completing successfully. The function
 * tries to cancel the migration and cleanup the remnants of the migration
 * on the VPLEX.
 *
 * @param vplexURI
 *            The URI of the VPLex storage system.
 * @param migrationURI
 *            The URI of the migration.
 * @param migrateStepId
 *            The migration step id.
 * @param stepId
 *            The rollback step id.
 * @throws WorkflowException
 */
public void rollbackMigrateVirtualVolume(URI vplexURI, URI migrationURI, String migrateStepId, String stepId) throws WorkflowException {
    Migration migration = null;
    String migrationVolumeLabel = null;
    try {
        // Update step state to executing.
        WorkflowStepCompleter.stepExecuting(stepId);
        // Was the migration created and started? If so, then
        // we'll try and cancel the migration and clean up.
        // Otherwise, there is nothing to do.
        Boolean migrationStarted = (Boolean) _workflowService.loadStepData(migrateStepId);
        if (!migrationStarted.booleanValue()) {
            // The migration was not successfully started.
            WorkflowStepCompleter.stepSucceded(stepId);
            return;
        }
        // Get the migration.
        migration = _dbClient.queryObject(Migration.class, migrationURI);
        // Get the VPLEX volume for the migration.
        Volume migrationVolume = _dbClient.queryObject(Volume.class, migration.getVolume());
        if (migrationVolume != null) {
            migrationVolumeLabel = migrationVolume.getLabel();
        }
        // cancel it now.
        if (!VPlexMigrationInfo.MigrationStatus.CANCELLED.getStatusValue().equals(migration.getMigrationStatus())) {
            _log.info("Cancel migration {}", migrationURI);
            // Get the VPlex API client.
            StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
            VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexSystem, _dbClient);
            _log.info("Got VPlex API client for VPlex {}", vplexURI);
            // Try to cancel the migration and cleanup and remove any
            // remnants of the migration.
            client.cancelMigrations(Arrays.asList(migration.getLabel()), true, true);
            _log.info("Migration cancelled");
        }
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (VPlexApiException vae) {
        // Do not allow rollback to go any further COP-21257
        _workflowService.setWorkflowRollbackContOnError(stepId, false);
        _log.error("Error during rollback of start migration: {}", vae.getMessage(), vae);
        if (migration != null) {
            setOrClearVolumeInternalFlag(migration.getVolume(), true);
            vae = VPlexApiException.exceptions.migrationRollbackFailureContactEMC(migration.getVolume().toString(), migrationVolumeLabel, migration.getLabel());
        }
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception e) {
        _log.error("Error during rollback of start migration: {}", e.getMessage());
        // Do not allow rollback to go any further COP-21257
        _workflowService.setWorkflowRollbackContOnError(stepId, false);
        if (migration != null) {
            setOrClearVolumeInternalFlag(migration.getVolume(), true);
            e = VPlexApiException.exceptions.migrationRollbackFailureContactEMC(migration.getVolume().toString(), migrationVolumeLabel, migration.getLabel());
        }
        WorkflowStepCompleter.stepFailed(stepId, VPlexApiException.exceptions.rollbackMigrateVolume(migrationURI.toString(), e));
    }
}
Also used : Volume(com.emc.storageos.db.client.model.Volume) Migration(com.emc.storageos.db.client.model.Migration) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) 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 32 with VPlexApiException

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

the class VPlexDeviceController method exportGroupAddVolumes.

/*
     * (non-Javadoc)
     *
     * @see com.emc.storageos.volumecontroller.impl.vplex.VplexController#exportAddVolume(java.net.URI, java.net.URI,
     * java.net.URI,
     * java.lang.Integer, java.lang.String)
     */
@Override
public void exportGroupAddVolumes(URI vplexURI, URI exportURI, Map<URI, Integer> volumeMap, String opId) throws ControllerException {
    String volListStr = "";
    ExportAddVolumeCompleter completer = null;
    try {
        WorkflowStepCompleter.stepExecuting(opId);
        completer = new ExportAddVolumeCompleter(exportURI, volumeMap, opId);
        volListStr = Joiner.on(',').join(volumeMap.keySet());
        Workflow workflow = _workflowService.getNewWorkflow(this, "exportGroupAddVolumes", true, opId);
        ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, exportURI);
        StorageSystem vplexSystem = _dbClient.queryObject(StorageSystem.class, vplexURI);
        URI srcVarray = exportGroup.getVirtualArray();
        boolean isRecoverPointExport = ExportUtils.checkIfInitiatorsForRP(_dbClient, exportGroup.getInitiators());
        if (!exportGroup.hasInitiators()) {
            // VPLEX API restricts adding volumes before initiators
            VPlexApiException.exceptions.cannotAddVolumesToExportGroupWithoutInitiators(exportGroup.forDisplay());
        }
        // Determine whether this export will be done across both VPLEX clusters,
        // or just the src or ha varray.
        // We get a map of varray to the volumes that can be exported in each varray.
        Map<URI, Set<URI>> varrayToVolumes = VPlexUtil.mapBlockObjectsToVarrays(_dbClient, volumeMap.keySet(), vplexURI, exportGroup);
        // Put the srcVolumes in their own set, and remove the src varray from the varrayToVolumes map.
        Set<URI> srcVolumes = varrayToVolumes.get(srcVarray);
        varrayToVolumes.remove(srcVarray);
        URI haVarray = null;
        // and we're not exporting to recover point initiators
        if (!varrayToVolumes.isEmpty() && !isRecoverPointExport) {
            if (exportGroup.hasAltVirtualArray(vplexURI.toString())) {
                // If we've already chosen an haVarray, go with with the choice
                haVarray = URI.create(exportGroup.getAltVirtualArrays().get(vplexURI.toString()));
            } else {
                // Otherwise we will make sure there is only one HA varray and persist it.
                haVarray = VPlexUtil.pickHAVarray(varrayToVolumes);
            }
        }
        // Partition the initiators by varray into varrayToInitiators map.
        List<URI> varrayURIs = new ArrayList<URI>();
        varrayURIs.add(exportGroup.getVirtualArray());
        if (haVarray != null) {
            varrayURIs.add(haVarray);
        }
        List<URI> exportGroupInitiatorList = StringSetUtil.stringSetToUriList(exportGroup.getInitiators());
        Map<URI, List<URI>> varrayToInitiators = VPlexUtil.partitionInitiatorsByVarray(_dbClient, exportGroupInitiatorList, varrayURIs, vplexSystem);
        if (varrayToInitiators.isEmpty()) {
            throw VPlexApiException.exceptions.exportCreateNoinitiatorsHaveCorrectConnectivity(exportGroup.getInitiators().toString(), varrayURIs.toString());
        }
        findAndUpdateFreeHLUsForClusterExport(vplexSystem, exportGroup, exportGroupInitiatorList, volumeMap);
        // Check if Zoning needs to be checked from system config
        // call the doZoneExportMasksCreate to check/create/remove zones with the flag
        String addZoneWhileAddingVolume = customConfigHandler.getComputedCustomConfigValue(CustomConfigConstants.ZONE_ADD_VOLUME, CustomConfigConstants.GLOBAL_KEY, null);
        // Default behavior is we allow zoning checks against the Network System
        Boolean addZoneOnDeviceOperation = true;
        _log.info("zoneExportAddVolumes checking for custom config value {} to skip zoning checks : (Default) : {}", addZoneWhileAddingVolume, addZoneOnDeviceOperation);
        if (addZoneWhileAddingVolume != null) {
            addZoneOnDeviceOperation = Boolean.valueOf(addZoneWhileAddingVolume);
            _log.info("Boolean convereted of : {} : returned by Config handler as : {} ", addZoneWhileAddingVolume, addZoneOnDeviceOperation);
        } else {
            _log.info("Config handler returned null for value so going by default value {}", addZoneOnDeviceOperation);
        }
        _log.info("zoneExportAddVolumes checking for custom config value {} to skip zoning checks : (Custom Config) : {}", addZoneWhileAddingVolume, addZoneOnDeviceOperation);
        // Add all the volumes to the SRC varray if there are src side volumes and
        // initiators that have connectivity to the source side.
        String srcExportStepId = null;
        if (varrayToInitiators.get(srcVarray) != null && srcVolumes != null) {
            srcExportStepId = assembleExportMasksWorkflow(vplexURI, exportURI, srcVarray, varrayToInitiators.get(srcVarray), ExportMaskUtils.filterVolumeMap(volumeMap, srcVolumes), addZoneOnDeviceOperation, workflow, null, opId);
        }
        // and there are volumes to be added to the ha varray, do so.
        if (haVarray != null && varrayToInitiators.get(haVarray) != null && varrayToVolumes.get(haVarray) != null) {
            exportGroup.putAltVirtualArray(vplexURI.toString(), haVarray.toString());
            _dbClient.updateObject(exportGroup);
            assembleExportMasksWorkflow(vplexURI, exportURI, haVarray, varrayToInitiators.get(haVarray), ExportMaskUtils.filterVolumeMap(volumeMap, varrayToVolumes.get(haVarray)), addZoneOnDeviceOperation, workflow, srcExportStepId, opId);
        }
        // Initiate the workflow.
        String message = String.format("VPLEX ExportGroup Add Volumes (%s) for export %s completed successfully", volListStr, exportURI);
        workflow.executePlan(completer, message);
    } catch (VPlexApiException vae) {
        String message = String.format("Failed to add Volumes %s to ExportGroup %s", volListStr, exportURI);
        _log.error(message, vae);
        failStep(completer, opId, vae);
    } catch (Exception ex) {
        String message = String.format("Failed to add Volumes %s to ExportGroup %s", volListStr, exportURI);
        _log.error(message, ex);
        String opName = ResourceOperationTypeEnum.ADD_EXPORT_VOLUME.getName();
        ServiceError serviceError = VPlexApiException.errors.exportGroupAddVolumesFailed(volListStr, exportURI.toString(), opName, ex);
        failStep(completer, opId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) Set(java.util.Set) HashSet(java.util.HashSet) StringSet(com.emc.storageos.db.client.model.StringSet) ArrayList(java.util.ArrayList) Workflow(com.emc.storageos.workflow.Workflow) 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) ApplicationAddVolumeList(com.emc.storageos.volumecontroller.ApplicationAddVolumeList) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) List(java.util.List) ExportAddVolumeCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportAddVolumeCompleter) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 33 with VPlexApiException

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

the class VPlexDeviceController method createMirrors.

/**
 * Do the creation of a VPlex Mirror device and attach it as a mirror to the Virtual Volume.
 * This is called as a Workflow Step.
 * NOTE: The parameters here must match createMirrorsMethod above (except stepId).
 *
 * @param vplexURI
 *            URI of the VPlex StorageSystem
 * @param vplexMirrorURIs
 *            URI of the mirrors to be created.
 * @param workflowTaskId
 *            The workflow taskId.
 * @param stepId
 *            The stepId used for completion.
 *
 * @throws WorkflowException
 *             When an error occurs updating the workflow step
 *             state.
 */
public void createMirrors(URI vplexURI, List<URI> vplexMirrorURIs, String workflowTaskId, String stepId) throws WorkflowException {
    List<VolumeInfo> rollbackData = new ArrayList<VolumeInfo>();
    List<URI> createdVplexMirrorURIs = new ArrayList<URI>();
    VplexMirrorTaskCompleter completer = new VplexMirrorTaskCompleter(VplexMirror.class, vplexMirrorURIs, workflowTaskId);
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        // Get the API client.
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        // Make a map of StorageSystem ids to Storage System
        Map<URI, StorageSystem> storageMap = new HashMap<URI, StorageSystem>();
        // Make a map of Mirrors to Storage Volumes.
        Map<VplexMirror, Volume> mirrorMap = new HashMap<VplexMirror, Volume>();
        for (URI vplexMirrorURI : vplexMirrorURIs) {
            VplexMirror vplexMirror = getDataObject(VplexMirror.class, vplexMirrorURI, _dbClient);
            // Find the underlying Storage Volume, there will be only one associated storage volume
            for (String associatedVolume : vplexMirror.getAssociatedVolumes()) {
                Volume storageVolume = getDataObject(Volume.class, new URI(associatedVolume), _dbClient);
                URI storageSystemId = storageVolume.getStorageController();
                if (storageMap.containsKey(storageSystemId) == false) {
                    StorageSystem storage = _dbClient.queryObject(StorageSystem.class, storageSystemId);
                    storageMap.put(storageSystemId, storage);
                }
                mirrorMap.put(vplexMirror, storageVolume);
            }
        }
        // Now make a call to the VPlexAPIClient.createDeviceAndAttachAsMirror for each vplex mirror.
        StringBuilder buf = new StringBuilder();
        buf.append("Vplex: " + vplexURI + " created mirror(s): ");
        for (VplexMirror vplexMirror : mirrorMap.keySet()) {
            URI vplexMirrorId = vplexMirror.getId();
            Volume sourceVplexVolume = getDataObject(Volume.class, vplexMirror.getSource().getURI(), _dbClient);
            VPlexVirtualVolumeInfo vplexVolumeInfo = new VPlexVirtualVolumeInfo();
            vplexVolumeInfo.setName(sourceVplexVolume.getDeviceLabel());
            vplexVolumeInfo.setPath(sourceVplexVolume.getNativeId());
            if (null == sourceVplexVolume.getAssociatedVolumes() || sourceVplexVolume.getAssociatedVolumes().isEmpty()) {
                _log.error("VPLEX volume {} has no backend volumes.", sourceVplexVolume.forDisplay());
                throw InternalServerErrorException.internalServerErrors.noAssociatedVolumesForVPLEXVolume(sourceVplexVolume.forDisplay());
            }
            if (sourceVplexVolume.getAssociatedVolumes().size() > 1) {
                vplexVolumeInfo.setLocality(VPlexApiConstants.DISTRIBUTED_VIRTUAL_VOLUME);
            } else {
                vplexVolumeInfo.setLocality(VPlexApiConstants.LOCAL_VIRTUAL_VOLUME);
            }
            _log.info(String.format("Creating mirror: %s (%s)", vplexMirror.getLabel(), vplexMirrorId));
            Volume storageVolume = mirrorMap.get(vplexMirror);
            long totalProvisioned = storageVolume.getProvisionedCapacity();
            StorageSystem storage = storageMap.get(storageVolume.getStorageController());
            List<String> itls = VPlexControllerUtils.getVolumeITLs(storageVolume);
            VolumeInfo vinfo = new VolumeInfo(storage.getNativeGuid(), storage.getSystemType(), storageVolume.getWWN().toUpperCase().replaceAll(":", ""), storageVolume.getNativeId(), storageVolume.getThinlyProvisioned().booleanValue(), itls);
            // Update rollback information.
            rollbackData.add(vinfo);
            List<VolumeInfo> vinfos = new ArrayList<VolumeInfo>();
            vinfos.add(vinfo);
            _workflowService.storeStepData(stepId, rollbackData);
            // Make the call to create device and attach it as mirror to the source virtual volume device.
            VPlexDeviceInfo vInfo = client.createDeviceAndAttachAsMirror(vplexVolumeInfo, vinfos, true, false);
            buf.append(vInfo.getName() + " ");
            _log.info(String.format("Created mirror : %s path: %s : for virtual volume %s device label %s", vInfo.getName(), vInfo.getPath(), sourceVplexVolume.getLabel(), sourceVplexVolume.getDeviceLabel()));
            vplexMirror.setNativeId(vInfo.getPath());
            vplexMirror.setDeviceLabel(vInfo.getName());
            // For Vplex virtual volumes set allocated capacity to 0 (cop-18608)
            vplexMirror.setAllocatedCapacity(0L);
            vplexMirror.setProvisionedCapacity(totalProvisioned);
            if (vplexVolumeInfo.isThinEnabled() != sourceVplexVolume.getThinlyProvisioned()) {
                _log.info("Thin provisioned setting changed after mirror operation to " + vplexVolumeInfo.isThinEnabled());
                sourceVplexVolume.setThinlyProvisioned(vplexVolumeInfo.isThinEnabled());
                _dbClient.updateObject(sourceVplexVolume);
            }
            vplexMirror.setThinlyProvisioned(vplexVolumeInfo.isThinEnabled());
            _dbClient.updateObject(vplexMirror);
            // Record VPLEX volume created event.
            createdVplexMirrorURIs.add(vplexMirrorId);
            recordBourneVplexMirrorEvent(vplexMirrorId, OperationTypeEnum.CREATE_VOLUME_MIRROR.getEvType(true), Operation.Status.ready, OperationTypeEnum.CREATE_VOLUME_MIRROR.getDescription());
        }
        completer.ready(_dbClient);
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (VPlexApiException vae) {
        _log.error("Exception creating Mirror for the Virtual Volume: " + vae.getMessage(), vae);
        // not created.
        for (URI vplexMirrorURI : vplexMirrorURIs) {
            if (!createdVplexMirrorURIs.contains(vplexMirrorURI)) {
                recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.CREATE_VOLUME_MIRROR.getEvType(false), Operation.Status.error, OperationTypeEnum.CREATE_VOLUME_MIRROR.getDescription());
            }
        }
        failStep(completer, stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception creating Mirror for the Virtual Volume: " + ex.getMessage(), ex);
        // not created.
        for (URI vplexMirrorURI : vplexMirrorURIs) {
            if (!createdVplexMirrorURIs.contains(vplexMirrorURI)) {
                recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.CREATE_VOLUME_MIRROR.getEvType(false), Operation.Status.error, OperationTypeEnum.CREATE_VOLUME_MIRROR.getDescription());
            }
        }
        ServiceError serviceError = VPlexApiException.errors.createMirrorsFailed(ex);
        failStep(completer, stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) VolumeInfo(com.emc.storageos.vplex.api.clientdata.VolumeInfo) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) VplexMirrorTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.VplexMirrorTaskCompleter) 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) Volume(com.emc.storageos.db.client.model.Volume) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) VPlexDeviceInfo(com.emc.storageos.vplex.api.VPlexDeviceInfo) VplexMirror(com.emc.storageos.db.client.model.VplexMirror) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 34 with VPlexApiException

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

the class VPlexDeviceController method attachMirror.

/**
 * Called to reattach the remote mirror for a distributed VPLEX volume upon
 * successfully restoring a native snapshot of the backend source volume.
 *
 * @param vplexURI
 *            The URI of the VPLEX system.
 * @param vplexVolumeURI
 *            The URI of the distributed VPLEX volume.
 * @param cgURI
 *            The URI of the volume's CG or null.
 * @param detachStepId
 *            The Id of the detach mirror step.
 * @param stepId
 *            The workflow step identifier.
 */
public void attachMirror(URI vplexURI, URI vplexVolumeURI, URI cgURI, String detachStepId, String stepId) {
    _log.info("Executing attach mirror to VPLEX volume {} on VPLEX {}", new Object[] { vplexVolumeURI, vplexURI });
    String mirrorDeviceName = "";
    try {
        // Update workflow step.
        WorkflowStepCompleter.stepExecuting(stepId);
        // Get the API client.
        StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexSystem, _dbClient);
        _log.info("Got VPLEX API client");
        // Get the VPLEX volume.
        Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
        String vplexVolumeName = vplexVolume.getDeviceLabel();
        _log.info("Got VPLEX volume");
        // Attach the mirror.
        @SuppressWarnings("unchecked") Map<String, String> detachStepData = (Map<String, String>) _workflowService.loadStepData(detachStepId);
        mirrorDeviceName = detachStepData.get(DETACHED_DEVICE);
        client.reattachMirrorToDistributedVolume(vplexVolumeName, mirrorDeviceName);
        _log.info("Attached the mirror");
        // On a subsequent failure, we don't want rollback to try to
        // reattach the mirror as it must have been successful here.
        // If the reattach fails, rollback will just end up trying again.
        detachStepData.put(REATTACH_MIRROR, Boolean.FALSE.toString());
        _workflowService.storeStepData(detachStepId, detachStepData);
        // If on detach it was required to temporarily modify the distributed device name
        // then we restore the correct name now after the volume is back together.
        String modifiedName = null;
        String successWarningMessage = null;
        String restoreDeviceName = detachStepData.get(RESTORE_DEVICE_NAME);
        if (restoreDeviceName != null) {
            try {
                modifiedName = restoreDeviceName.substring(0, VPlexApiConstants.MAX_DEVICE_NAME_LENGTH_FOR_ATTACH_MIRROR);
                client.renameDistributedDevice(modifiedName, restoreDeviceName);
                _log.info("Restored name of distributed device from {} to {}", modifiedName, restoreDeviceName);
            } catch (Exception e) {
                // We don't fail the workflow step in this case, but instead just log a message
                // indicating this error. The distributed device for the volume will just have
                // the modified name.
                successWarningMessage = String.format("Failed renaming the distributed device %s back " + " to its orginal name %s after reattaching remote mirror", modifiedName, restoreDeviceName);
                _log.warn(successWarningMessage);
            }
            // Remove the entry in the step data. We do this regardless of success
            // or failure so that we don't try and rename again in a rollback
            // scenario.
            detachStepData.remove(RESTORE_DEVICE_NAME);
        }
        // If the volume is in a CG, we can now add it back.
        if (cgURI != null) {
            ConsistencyGroupManager consistencyGroupManager = getConsistencyGroupManager(vplexVolume);
            consistencyGroupManager.addVolumeToCg(cgURI, vplexVolume, client, false);
            // No need to try and add it back in rollback if something
            // fails in the step after this point. If the add fails
            // here, rollback will just try again.
            detachStepData.put(ADD_BACK_TO_CG, Boolean.FALSE.toString());
            _workflowService.storeStepData(detachStepId, detachStepData);
            _log.info("Added volume back to consistency group.");
        }
        // Update workflow step state to success.
        if (successWarningMessage != null) {
            WorkflowStepCompleter.stepSucceeded(stepId, successWarningMessage);
        } else {
            WorkflowStepCompleter.stepSucceded(stepId);
        }
        _log.info("Updated workflow step state to success");
    } catch (VPlexApiException vae) {
        _log.error("Exception attaching mirror for VPLEX distributed volume" + vae.getMessage(), vae);
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception e) {
        _log.error("Exception attaching mirror for VPLEX distributed volume " + e.getMessage(), e);
        WorkflowStepCompleter.stepFailed(stepId, VPlexApiException.exceptions.failedAttachingVPlexVolumeMirror(mirrorDeviceName, vplexVolumeURI.toString(), e));
    }
}
Also used : Volume(com.emc.storageos.db.client.model.Volume) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) Map(java.util.Map) OpStatusMap(com.emc.storageos.db.client.model.OpStatusMap) HashMap(java.util.HashMap) StringMap(com.emc.storageos.db.client.model.StringMap) 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 35 with VPlexApiException

use of com.emc.storageos.vplex.api.VPlexApiException 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)

Aggregations

VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)59 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)53 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)43 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)43 ControllerException (com.emc.storageos.volumecontroller.ControllerException)43 WorkflowException (com.emc.storageos.workflow.WorkflowException)43 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)41 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)41 VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)40 URI (java.net.URI)39 ArrayList (java.util.ArrayList)39 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)34 IOException (java.io.IOException)34 URISyntaxException (java.net.URISyntaxException)34 ExportMask (com.emc.storageos.db.client.model.ExportMask)26 Volume (com.emc.storageos.db.client.model.Volume)25 NamedURI (com.emc.storageos.db.client.model.NamedURI)21 Initiator (com.emc.storageos.db.client.model.Initiator)20 BlockStorageDevice (com.emc.storageos.volumecontroller.BlockStorageDevice)14 VPlexVirtualVolumeInfo (com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo)12