Search in sources :

Example 26 with VPlexApiException

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

the class VPlexDeviceController method expandVirtualVolume.

/**
 * Expands the virtual volume with the passed URI to it full expandable capacity.
 *
 * @param vplexSystemURI
 *            The URI of the VPlex system.
 * @param vplexVolumeURI
 *            The URI of the VPlex volume to expand.
 * @param newSize
 *            The new requested volume size.
 * @param systemNativeGuids
 *            The URIs of the backend storage systems, or null
 * @param stepId
 *            The workflow step identifier.
 *
 * @throws WorkflowException
 *             When an error occurs updating the work step state.
 */
public void expandVirtualVolume(URI vplexSystemURI, URI vplexVolumeURI, Long newSize, List<String> systemNativeGuids, String stepId) throws WorkflowException {
    try {
        // Update step state to executing.
        WorkflowStepCompleter.stepExecuting(stepId);
        // Get the virtual volume.
        Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
        String vplexVolumeName = vplexVolume.getDeviceLabel();
        _log.info("Virtual volume name is {}", vplexVolumeName);
        // Get the VPlex API client.
        StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexSystemURI, _dbClient);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexSystem, _dbClient);
        _log.info("Got VPlex API client for VPlex system {}", vplexSystemURI);
        // arrays to pick up the new expanded volume size.
        if (systemNativeGuids != null) {
            client.rediscoverStorageSystems(systemNativeGuids);
            // Async code.
            try {
                Thread.sleep(60000);
            } catch (Exception e) {
                // ignore exceptions
                _log.warn("thread sleep exception " + e.getLocalizedMessage());
            }
        }
        // Make a call to the VPlex API client to expand the virtual
        // volume.
        int expansionStatusRetryCount = Integer.valueOf(ControllerUtils.getPropertyValueFromCoordinator(coordinator, VPlexApiConstants.EXPANSION_STATUS_RETRY_COUNT));
        long expansionStatusSleepTime = Long.valueOf(ControllerUtils.getPropertyValueFromCoordinator(coordinator, VPlexApiConstants.EXPANSION_STATUS_SLEEP_TIME_MS));
        VPlexVirtualVolumeInfo vplexVolumeInfo = client.expandVirtualVolume(vplexVolumeName, expansionStatusRetryCount, expansionStatusSleepTime);
        _log.info("Completed VPlex volume expansion");
        // Update the VPlex volume size in the database.
        vplexVolume.setCapacity(newSize);
        vplexVolume.setProvisionedCapacity(vplexVolumeInfo.getCapacityBytes());
        // For Vplex virtual volumes set allocated capacity to 0 (cop-18608)
        vplexVolume.setAllocatedCapacity(0L);
        _dbClient.updateObject(vplexVolume);
        _log.info("Updated volume size");
        // Update step status to success.
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (VPlexApiException vae) {
        _log.error("Exception expanding VPlex virtual volume: " + vae.getMessage(), vae);
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception expanding VPlex virtual volume: " + ex.getMessage(), ex);
        String opName = ResourceOperationTypeEnum.EXPAND_VIRTUAL_VOLUME.getName();
        ServiceError serviceError = VPlexApiException.errors.expandVirtualVolumeFailed(opName, ex);
        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) 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) AlternateIdConstraint(com.emc.storageos.db.client.constraint.AlternateIdConstraint) ContainmentConstraint(com.emc.storageos.db.client.constraint.ContainmentConstraint) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 27 with VPlexApiException

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

the class VPlexDeviceController method createVirtualVolumeFromImportStep.

/**
 * Create a Virtual Volume from an Imported Volume.
 * There are three cases here:
 * 1. We want to create a non-distributed virtual volume. In this case,
 * there is an existingVolume, but newVolume == null.
 * 2. We want to create a distributed virtual volume from an existing volume,
 * and then add a mirror to a new volume (in the other varray).
 * In this case, both existingVolume and newVolume are non-null.
 * 3. We had an existing Virtual volume, and we only want to upgrade it
 * to a distributed Virtual Volume (existingVolumeURI == null).
 *
 * @param vplexURI
 * @param vplexVolumeURI
 * @param existingVolumeURI
 * @param newVolumeURI
 * @param vplexSystemProject
 * @param vplexSystemTenant
 * @param newCosURI
 * @param newLabel
 * @param stepId
 * @throws WorkflowException
 */
public void createVirtualVolumeFromImportStep(URI vplexURI, URI vplexVolumeURI, URI existingVolumeURI, URI newVolumeURI, URI vplexSystemProject, URI vplexSystemTenant, URI newCosURI, String newLabel, String transferSize, String stepId) throws WorkflowException {
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        // Get the API client.
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        // Get the three volumes.
        Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
        Volume existingVolume = null;
        Volume newVolume = null;
        if (existingVolumeURI != null) {
            existingVolume = getDataObject(Volume.class, existingVolumeURI, _dbClient);
        }
        if (newVolumeURI != null) {
            newVolume = getDataObject(Volume.class, newVolumeURI, _dbClient);
        }
        VPlexVirtualVolumeInfo virtvinfo = null;
        VolumeInfo vinfo = null;
        // Make the call to create the (non-distributed) virtual volume.
        if (existingVolume != null) {
            StorageSystem array = getDataObject(StorageSystem.class, existingVolume.getStorageController(), _dbClient);
            List<String> itls = VPlexControllerUtils.getVolumeITLs(existingVolume);
            List<VolumeInfo> vinfos = new ArrayList<VolumeInfo>();
            VirtualPool newVirtualPool = getDataObject(VirtualPool.class, newCosURI, _dbClient);
            boolean thinEnabled = VirtualPool.ProvisioningType.Thin.toString().equalsIgnoreCase(newVirtualPool.getSupportedProvisioningType());
            vinfo = new VolumeInfo(array.getNativeGuid(), array.getSystemType(), existingVolume.getWWN().toUpperCase().replaceAll(":", ""), existingVolume.getNativeId(), thinEnabled, itls);
            vinfos.add(vinfo);
            thinEnabled = thinEnabled && verifyVplexSupportsThinProvisioning(vplex);
            virtvinfo = client.createVirtualVolume(vinfos, false, true, true, null, null, true, thinEnabled, true);
            // Note: According to client.createVirtualVolume code, this will never be the case (null)
            if (virtvinfo == null) {
                String opName = ResourceOperationTypeEnum.CREATE_VVOLUME_FROM_IMPORT.getName();
                ServiceError serviceError = VPlexApiException.errors.createVirtualVolumeFromImportStepFailed(opName);
                WorkflowStepCompleter.stepFailed(stepId, serviceError);
                return;
            }
            _log.info(String.format("Created virtual volume: %s path: %s thinEnabled: %b", virtvinfo.getName(), virtvinfo.getPath(), virtvinfo.isThinEnabled()));
            checkThinEnabledResult(virtvinfo, thinEnabled, _workflowService.getWorkflowFromStepId(stepId).getOrchTaskId());
            // not set.
            if (newVolume != null) {
                vplexVolume.setNativeId(virtvinfo.getPath());
                vplexVolume.setNativeGuid(virtvinfo.getPath());
                vplexVolume.setDeviceLabel(virtvinfo.getName());
                vplexVolume.setThinlyProvisioned(virtvinfo.isThinEnabled());
                _dbClient.updateObject(vplexVolume);
            }
        } else {
            virtvinfo = client.findVirtualVolume(vplexVolume.getDeviceLabel(), vplexVolume.getNativeId());
        }
        // now create a mirror to the new volume.
        if (newVolume != null) {
            String clusterId = ConnectivityUtil.getVplexClusterForVarray(vplexVolume.getVirtualArray(), vplexVolume.getStorageController(), _dbClient);
            StorageSystem array = getDataObject(StorageSystem.class, newVolume.getStorageController(), _dbClient);
            List<String> itls = VPlexControllerUtils.getVolumeITLs(newVolume);
            vinfo = new VolumeInfo(array.getNativeGuid(), array.getSystemType(), newVolume.getWWN().toUpperCase().replaceAll(":", ""), newVolume.getNativeId(), newVolume.getThinlyProvisioned().booleanValue(), itls);
            // Add rollback data.
            _workflowService.storeStepData(stepId, vinfo);
            virtvinfo = client.upgradeVirtualVolumeToDistributed(virtvinfo, vinfo, true, clusterId, transferSize);
            if (virtvinfo == null) {
                String opName = ResourceOperationTypeEnum.UPGRADE_VPLEX_LOCAL_TO_DISTRIBUTED.getName();
                ServiceError serviceError = VPlexApiException.errors.upgradeLocalToDistributedFailed(opName);
                WorkflowStepCompleter.stepFailed(stepId, serviceError);
                return;
            }
        }
        // Update the virtual volume device label and native Id.
        // Also make sure the WWN is set.
        vplexVolume.setNativeId(virtvinfo.getPath());
        vplexVolume.setNativeGuid(virtvinfo.getPath());
        vplexVolume.setDeviceLabel(virtvinfo.getName());
        vplexVolume.setThinlyProvisioned(virtvinfo.isThinEnabled());
        vplexVolume.setWWN(virtvinfo.getWwn());
        // If we are importing, we need to move the existing import volume to
        // the system project/tenant, update its label, and set the new CoS.
        Volume srcSideAssocVolume = null;
        if (existingVolume != null) {
            srcSideAssocVolume = existingVolume;
            existingVolume.setProject(new NamedURI(vplexSystemProject, existingVolume.getLabel()));
            existingVolume.setTenant(new NamedURI(vplexSystemTenant, existingVolume.getLabel()));
            existingVolume.setLabel(newLabel);
            existingVolume.setVirtualPool(newCosURI);
            existingVolume.addInternalFlags(Flag.INTERNAL_OBJECT);
            _dbClient.updateObject(existingVolume);
            // If the VPLEX volume is being upgraded to distributed, it's provisioned
            // should be set and does not change. However, when importing an existing
            // volume to a VPLEX volume, we need to set the provisioned capacity
            // of the VPLEX volume to the provisioned capacity of the existing volume.
            vplexVolume.setProvisionedCapacity(existingVolume.getProvisionedCapacity());
            // For Vplex virtual volumes set allocated capacity to 0 (cop-18608)
            vplexVolume.setAllocatedCapacity(0L);
            // For import associated with creating a VPLEX full copy, we need
            // to add the copy to the list of copies for the source VPLEX volume.
            // We only do this when the copy is successfully completed.
            URI srcVplexVolumeURI = vplexVolume.getAssociatedSourceVolume();
            if (!NullColumnValueGetter.isNullURI(srcVplexVolumeURI)) {
                // Note that the associated source volume will be null if
                // this is just a standard import of a non-VPLEX volume. It
                // will be set in the case we use the import workflow to
                // import a native copy to a VPLEX volume for the purpose
                // of creating a full copy.
                Volume srcVplexVolume = _dbClient.queryObject(Volume.class, srcVplexVolumeURI);
                if (null != srcVplexVolume) {
                    StringSet srcVplexVolumeCopies = srcVplexVolume.getFullCopies();
                    if (srcVplexVolumeCopies == null) {
                        srcVplexVolumeCopies = new StringSet();
                        srcVplexVolume.setFullCopies(srcVplexVolumeCopies);
                    }
                    srcVplexVolumeCopies.add(vplexVolumeURI.toString());
                    _dbClient.updateObject(srcVplexVolume);
                }
                // Also, reflect the replica state in the vplex copy.
                vplexVolume.setReplicaState(existingVolume.getReplicaState());
            }
        } else {
            // and update the CoS.
            for (String assocVolume : vplexVolume.getAssociatedVolumes()) {
                try {
                    srcSideAssocVolume = _dbClient.queryObject(Volume.class, new URI(assocVolume));
                    srcSideAssocVolume.setVirtualPool(newCosURI);
                    _dbClient.updateObject(srcSideAssocVolume);
                } catch (URISyntaxException ex) {
                    _log.error("Bad assocVolume URI: " + assocVolume, ex);
                }
            }
            vplexVolume.getAssociatedVolumes().add(newVolumeURI.toString());
            vplexVolume.setVirtualPool(newCosURI);
        }
        // created and we need to make sure it has the correct name.
        try {
            if ((CustomVolumeNamingUtils.isCustomVolumeNamingEnabled(customConfigHandler, vplex.getSystemType())) && (existingVolume != null)) {
                // Create the VPLEX volume name custom configuration datasource and generate the
                // custom volume name.
                String customConfigName = CustomVolumeNamingUtils.getCustomConfigName(false);
                Project project = getDataObject(Project.class, vplexVolume.getProject().getURI(), _dbClient);
                TenantOrg tenant = getDataObject(TenantOrg.class, vplexVolume.getTenant().getURI(), _dbClient);
                DataSource customNameDataSource = CustomVolumeNamingUtils.getCustomConfigDataSource(project, tenant, vplexVolume.getLabel(), vplexVolume.getWWN(), null, dataSourceFactory, customConfigName, _dbClient);
                if (customNameDataSource != null) {
                    String customVolumeName = CustomVolumeNamingUtils.getCustomName(customConfigHandler, customConfigName, customNameDataSource, vplex.getSystemType());
                    virtvinfo = CustomVolumeNamingUtils.renameVolumeOnVPlex(virtvinfo, customVolumeName, client);
                    vplexVolume.setNativeId(virtvinfo.getPath());
                    vplexVolume.setNativeGuid(virtvinfo.getPath());
                    vplexVolume.setDeviceLabel(virtvinfo.getName());
                    vplexVolume.setLabel(virtvinfo.getName());
                    // Also, we update the name portion of the project and tenant URIs
                    // to reflect the custom name. This is necessary because the API
                    // to search for volumes by project, extracts the name portion of the
                    // project URI to get the volume name.
                    NamedURI namedURI = vplexVolume.getProject();
                    namedURI.setName(virtvinfo.getName());
                    vplexVolume.setProject(namedURI);
                    namedURI = vplexVolume.getTenant();
                    namedURI.setName(virtvinfo.getName());
                    vplexVolume.setTenant(namedURI);
                }
            }
        } catch (Exception e) {
            _log.warn(String.format("Error attempting to rename VPLEX volume %s", vplexVolumeURI), e);
        }
        // Update the volume.
        _dbClient.updateObject(vplexVolume);
        // Complete the workflow step.
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (VPlexApiException vae) {
        if (existingVolumeURI != null) {
            _log.error("Exception importing non-VPLEX volume to VPLEX: " + vae.getMessage(), vae);
        } else {
            _log.error("Exception upgrading a local VPLEX volume to distributed: " + vae.getMessage(), vae);
        }
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception ex) {
        ServiceError serviceError;
        if (existingVolumeURI != null) {
            _log.error("Exception importing non-VPLEX volume to VPLEX: " + ex.getMessage(), ex);
            String opName = ResourceOperationTypeEnum.IMPORT_BLOCK_VOLUME.getName();
            serviceError = VPlexApiException.errors.importVolumeFailedException(opName, ex);
        } else {
            _log.error("Exception upgrading a local VPLEX volume to distributed: " + ex.getMessage(), ex);
            String opName = ResourceOperationTypeEnum.UPGRADE_VPLEX_LOCAL_TO_DISTRIBUTED.getName();
            serviceError = VPlexApiException.errors.upgradeLocalToDistributedFailedException(opName, ex);
        }
        WorkflowStepCompleter.stepFailed(stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) NamedURI(com.emc.storageos.db.client.model.NamedURI) ArrayList(java.util.ArrayList) VolumeInfo(com.emc.storageos.vplex.api.clientdata.VolumeInfo) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) URISyntaxException(java.net.URISyntaxException) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) 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) DataSource(com.emc.storageos.customconfigcontroller.DataSource) Project(com.emc.storageos.db.client.model.Project) Volume(com.emc.storageos.db.client.model.Volume) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) StringSet(com.emc.storageos.db.client.model.StringSet) TenantOrg(com.emc.storageos.db.client.model.TenantOrg) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 28 with VPlexApiException

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

the class VPlexDeviceController method waitOnRebuild.

/**
 * Waits for the rebuild to complete when a non-VPLEX volume is imported to a VPLEX
 * distribute volume or a local VPLEX volume is upgraded to distributed.
 *
 * @param vplexURI
 *            The URI of the VPLEX system.
 * @param vplexVolumeURI
 *            The URI of the VPLEX volume.
 * @param stepId
 *            The workflow step identifier.
 *
 * @throws WorkflowException
 */
public void waitOnRebuild(URI vplexURI, URI vplexVolumeURI, String stepId) throws WorkflowException {
    String volumeName = null;
    try {
        // Update step state to executing.
        WorkflowStepCompleter.stepExecuting(stepId);
        // Get the API client.
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        // Get the VPLEX volume that is rebuilding.
        Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
        volumeName = vplexVolume.getLabel();
        // Check the rebuild status until it completes, fails, or we timeout waiting.
        WaitOnRebuildResult rebuildResult = client.waitOnRebuildCompletion(vplexVolume.getDeviceLabel());
        _log.info(String.format("Finished waiting on rebuild for virtual volume: %s path: %s rebuild-status: %s", vplexVolume.getDeviceLabel(), vplexVolume.getNativeId(), rebuildResult.name()));
        if (WaitOnRebuildResult.SUCCESS == rebuildResult) {
            WorkflowStepCompleter.stepSucceded(stepId);
        } else {
            ServiceError serviceError;
            if (WaitOnRebuildResult.FAILED == rebuildResult) {
                serviceError = VPlexApiException.errors.waitOnRebuildFailed(volumeName);
            } else if (WaitOnRebuildResult.TIMED_OUT == rebuildResult) {
                serviceError = VPlexApiException.errors.waitOnRebuildTimedOut(volumeName);
            } else {
                serviceError = VPlexApiException.errors.waitOnRebuildInvalid(volumeName);
            }
            WorkflowStepCompleter.stepFailed(stepId, serviceError);
        }
    } catch (VPlexApiException vae) {
        _log.error("Exception checking the rebuild status: " + vae.getMessage(), vae);
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception checking the rebuild status: " + ex.getMessage(), ex);
        ServiceError serviceError = VPlexApiException.errors.waitOnRebuildException(volumeName, ex);
        WorkflowStepCompleter.stepFailed(stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) Volume(com.emc.storageos.db.client.model.Volume) WaitOnRebuildResult(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo.WaitOnRebuildResult) 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 29 with VPlexApiException

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

the class VPlexDeviceController method rollbackUpgradeVirtualVolumeLocalToDistributed.

/**
 * Rollback upgrade of VPLEX local to VPLEX distributed volume.
 *
 * @param vplexURI
 *            Reference to VPLEX system
 * @param virtualVolumeName
 *            Virtual volume name which was supposed to be upgraded
 * @param virtualVolumePath
 *            Virtual volume path which was supposed to be upgraded
 * @param executeStepId
 *            step Id of the execute step; used to retrieve rollback data
 * @param stepId
 *            The rollback step id
 * @throws WorkflowException
 *             When an error occurs updating the workflow step state
 */
public void rollbackUpgradeVirtualVolumeLocalToDistributed(URI vplexURI, String virtualVolumeName, String virtualVolumePath, String executeStepId, String stepId) throws WorkflowException {
    try {
        VolumeInfo mirrorInfo = (VolumeInfo) _workflowService.loadStepData(executeStepId);
        if (mirrorInfo != null) {
            WorkflowStepCompleter.stepExecuting(stepId);
            // Get the API client.
            StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
            VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
            // Get the cluster id for this storage volume.
            String clusterId = client.getClaimedStorageVolumeClusterName(mirrorInfo);
            try {
                // Try to detach mirror that might have been added.
                client.detachMirrorFromDistributedVolume(virtualVolumeName, clusterId);
                // Find virtual volume and its supporting device
                VPlexVirtualVolumeInfo virtualVolumeInfo = client.findVirtualVolume(virtualVolumeName, virtualVolumePath);
                String sourceDeviceName = virtualVolumeInfo.getSupportingDevice();
                // Once mirror is detached we need to do device collapse so that its not seen as distributed device.
                client.deviceCollapse(sourceDeviceName, VPlexApiConstants.DISTRIBUTED_DEVICE);
                // Once device collapse is successful we need to set visibility of device to local because volume will be seen from
                // other cluster still as visibility of device changes to global once mirror is attached.
                client.setDeviceVisibility(sourceDeviceName);
            } catch (Exception e) {
                _log.error("Exception restoring virtual volume " + virtualVolumeName + " to its original state." + e);
                _log.info(String.format("Couldn't detach mirror corresponding to the backend volume %s from the VPLEX volume %s on VPLEX cluster %s during rollback. " + "Its possible mirror was never attached, so just move on to delete backend volume artifacts from the VPLEX", mirrorInfo.getVolumeName(), virtualVolumeName, clusterId));
            }
            // Its possible that mirror was never attached so we will try to delete the device even if we fail to
            // detach a mirror.
            // If mirror device is still attached this will anyway fail, so its safe to make this call.
            client.deleteLocalDevice(mirrorInfo);
        }
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (VPlexApiException vae) {
        _log.error("Exception rollback VPlex Virtual Volume upgrade from local to distributed : " + vae.getLocalizedMessage(), vae);
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception rollback VPlex Virtual Volume upgrade from local to distributed : " + 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) VolumeInfo(com.emc.storageos.vplex.api.clientdata.VolumeInfo) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) 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 30 with VPlexApiException

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

the class VPlexDeviceController method deleteVirtualVolumes.

/**
 * A workflow Step to delete VPLex Virtual volumes.
 * This Step is also used to rollback create virtual volumes.
 * NOTE NOTE: The parameters here must match deleteVirtualVolumesMethod above (except stepId).
 *
 * @param vplexURI
 * @param volumeURIs
 * @param doNotFullyDeleteVolumeList
 * @param stepId
 * @throws WorkflowException
 */
public void deleteVirtualVolumes(URI vplexURI, List<URI> volumeURIs, List<URI> doNotFullyDeleteVolumeList, String stepId) throws WorkflowException {
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexURI, _dbClient);
        StringBuilder errMsgBuilder = new StringBuilder();
        boolean failed = false;
        // Loop deleting each volume by name (the deviceLabel in the Volume).
        for (URI volumeURI : volumeURIs) {
            Volume volume = _dbClient.queryObject(Volume.class, volumeURI);
            if (volume == null || volume.getInactive() == true) {
                continue;
            }
            // Skip this operation if the volume has already been deleted
            if (volume.getDeviceLabel() == null) {
                _log.info("Volume {} with Id {} was never created on the Vplex as device label is null " + "hence skip volume delete on VPLEX", volume.getLabel(), volume.getId());
                continue;
            }
            try {
                client.findVirtualVolume(volume.getDeviceLabel(), volume.getNativeId());
            } catch (VPlexApiException ex) {
                if (ex.getServiceCode() == ServiceCode.VPLEX_CANT_FIND_REQUESTED_VOLUME) {
                    _log.info("VPlex virtual volume: " + volume.getNativeId() + " has already been deleted; will skip deletion of virtual volume");
                    continue;
                } else {
                    _log.error("Exception finding Virtual Volume", ex);
                    throw ex;
                }
            }
            try {
                if (volume.getNativeId() != null) {
                    // Volumes in consistency groups must be removed.
                    BlockConsistencyGroup cg = null;
                    if (!NullColumnValueGetter.isNullURI(volume.getConsistencyGroup())) {
                        cg = getDataObject(BlockConsistencyGroup.class, volume.getConsistencyGroup(), _dbClient);
                    }
                    if (cg != null) {
                        // Call the appropriate ConsistencyGroupManager to delete the CG volume
                        ConsistencyGroupManager consistencyGroupManager = getConsistencyGroupManager(volume);
                        consistencyGroupManager.deleteConsistencyGroupVolume(vplexURI, volume, cg);
                    }
                    // to delete volume.
                    if (doNotFullyDeleteVolumeList == null || doNotFullyDeleteVolumeList.isEmpty() || !doNotFullyDeleteVolumeList.contains(volume.getId())) {
                        // We only retry a dismantle failure on volumes created
                        // in ViPR as the retry code relies on the well-known ViPR
                        // naming conventions and virtual volume structure to find
                        // VPLEX artifacts related to the volume being deleted.
                        _log.info(String.format("Deleting VPlex virtual volume %s (%s)", volume.getDeviceLabel(), volume.getNativeId()));
                        boolean isIngestedWithoutBackend = volume.isIngestedVolumeWithoutBackend(_dbClient);
                        client.deleteVirtualVolume(volume.getDeviceLabel(), !isIngestedWithoutBackend, !isIngestedWithoutBackend);
                    }
                    // Record VPLEX volume deleted event.
                    recordBourneVolumeEvent(volume.getId(), OperationTypeEnum.DELETE_BLOCK_VOLUME.getEvType(true), Operation.Status.ready, OperationTypeEnum.DELETE_BLOCK_VOLUME.getDescription());
                    if (volume.getMirrors() != null && !(volume.getMirrors().isEmpty())) {
                        for (String mirrorId : volume.getMirrors()) {
                            VplexMirror mirror = _dbClient.queryObject(VplexMirror.class, URI.create(mirrorId));
                            if (null != mirror) {
                                _log.info("Marking mirror {} {} for deletion.", mirror.getId(), mirror.getDeviceLabel());
                                _dbClient.removeObject(mirror);
                            }
                        }
                    }
                }
            } catch (Exception ex) {
                _log.error("Exception deleting Virtual Volume: " + volumeURI, ex);
                // Record VPLEX volume deletion failed event.
                recordBourneVolumeEvent(volume.getId(), OperationTypeEnum.DELETE_BLOCK_VOLUME.getEvType(false), Operation.Status.error, OperationTypeEnum.DELETE_BLOCK_VOLUME.getDescription());
                // Update error message
                if (errMsgBuilder.length() != 0) {
                    errMsgBuilder.append("\n");
                } else {
                    errMsgBuilder.append("Exception deleting vplex virtual volume(s):\n");
                }
                errMsgBuilder.append(volume.getLabel());
                errMsgBuilder.append(":");
                errMsgBuilder.append(ex.getMessage());
                failed = true;
            }
        }
        if (failed) {
            String opName = ResourceOperationTypeEnum.DELETE_VIRTUAL_VOLUME.getName();
            ServiceError serviceError = VPlexApiException.errors.jobFailedOp(opName);
            serviceError.setMessage(errMsgBuilder.toString());
            WorkflowStepCompleter.stepFailed(stepId, serviceError);
        } else {
            WorkflowStepCompleter.stepSucceded(stepId);
        }
    } catch (VPlexApiException vae) {
        _log.error("Exception deleting VPlex Virtual Volume: " + vae.getMessage(), vae);
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception deleting VPlex Virtual Volume: " + ex.getMessage(), ex);
        String opName = ResourceOperationTypeEnum.DELETE_VIRTUAL_VOLUME.getName();
        ServiceError serviceError = VPlexApiException.errors.deleteVirtualVolumesFailed(opName, ex);
        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) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) 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) BlockConsistencyGroup(com.emc.storageos.db.client.model.BlockConsistencyGroup)

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