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);
}
}
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);
}
}
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);
}
}
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);
}
}
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);
}
}
Aggregations