use of com.emc.storageos.vplex.api.VPlexApiClient in project coprhd-controller by CoprHD.
the class VPlexDeviceController method validateVPlexVolume.
/**
* Validates that the backend volumes of the passed VPLEX volumes in the
* ViPR database are the actual backend volumes used by the VPLEX volume
* on the VPLEX system.
*
* @param vplexSystemURI
* The URI of the VPLEX storage system.
* @param vplexVolumeURI
* The URI of the VPLEX volume to validate.
* @param stepId
* The workflow step id.
*/
public void validateVPlexVolume(URI vplexSystemURI, URI vplexVolumeURI, String stepId) {
Volume vplexVolume = null;
try {
// Skip this if validation disabled
ValidatorConfig validatorConfig = new ValidatorConfig();
validatorConfig.setCoordinator(coordinator);
if (!validatorConfig.isValidationEnabled()) {
WorkflowStepCompleter.stepSucceeded(stepId, "Validations not enabled");
return;
}
// Update step state to executing.
WorkflowStepCompleter.stepExecuting(stepId);
// Get the VPLEX API client for the VPLEX system.
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexSystemURI, _dbClient);
// Get the VPLEX volume
vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
// Get a VolumeInfo for each backend volume and any mirrors, mapped by VPLEX cluster name.
Set<String> volumeIds = new HashSet<>();
Map<String, List<VolumeInfo>> volumeInfoMap = new HashMap<>();
StringSet associatedVolumeIds = vplexVolume.getAssociatedVolumes();
if ((associatedVolumeIds == null) || (associatedVolumeIds.isEmpty())) {
// Ingested volume w/o backend volume ingestion. We can't verify the backend volumes.
_log.info("VPLEX volume {}:{} has no backend volumes to validate", vplexVolumeURI, vplexVolume.getLabel());
WorkflowStepCompleter.stepSucceded(stepId);
return;
} else {
volumeIds.addAll(associatedVolumeIds);
}
// Now mirrors.
StringSet mirrorIds = vplexVolume.getMirrors();
if ((mirrorIds != null) && (mirrorIds.isEmpty() == false)) {
for (String mirrorId : mirrorIds) {
VplexMirror mirror = getDataObject(VplexMirror.class, URI.create(mirrorId), _dbClient);
StringSet associatedVolumeIdsForMirror = mirror.getAssociatedVolumes();
if ((associatedVolumeIdsForMirror == null) || (associatedVolumeIdsForMirror.isEmpty())) {
_log.info("VPLEX mirror {}:{} has no associated volumes", mirrorId, mirror.getLabel());
throw DeviceControllerExceptions.vplex.vplexMirrorDoesNotHaveAssociatedVolumes(vplexVolume.getLabel(), mirror.getLabel());
} else {
volumeIds.addAll(associatedVolumeIdsForMirror);
}
}
}
// Get the WWNs for these volumes mapped by VPLEX cluster name.
for (String volumesId : volumeIds) {
URI volumeURI = URI.create(volumesId);
Volume volume = getDataObject(Volume.class, volumeURI, _dbClient);
String clusterName = VPlexUtil.getVplexClusterName(volume.getVirtualArray(), vplexSystemURI, client, _dbClient);
StorageSystem storageSystem = getDataObject(StorageSystem.class, volume.getStorageController(), _dbClient);
List<String> itls = VPlexControllerUtils.getVolumeITLs(volume);
VolumeInfo volumeInfo = new VolumeInfo(storageSystem.getNativeGuid(), storageSystem.getSystemType(), volume.getWWN().toUpperCase().replaceAll(":", ""), volume.getNativeId(), volume.getThinlyProvisioned().booleanValue(), itls);
_log.info(String.format("Validating backend volume %s on cluster %s", volumeURI, clusterName));
if (volumeInfoMap.containsKey(clusterName)) {
List<VolumeInfo> clusterVolumeInfos = volumeInfoMap.get(clusterName);
clusterVolumeInfos.add(volumeInfo);
} else {
List<VolumeInfo> clusterVolumeInfos = new ArrayList<>();
clusterVolumeInfos.add(volumeInfo);
volumeInfoMap.put(clusterName, clusterVolumeInfos);
}
}
// Validate the ViPR backend volume WWNs match those on the VPLEX.
client.validateBackendVolumesForVPlexVolume(vplexVolume.getDeviceLabel(), vplexVolume.getNativeId(), volumeInfoMap);
WorkflowStepCompleter.stepSucceded(stepId);
} catch (InternalException ie) {
_log.info("Exception attempting to validate the backend volumes for VPLEX volume {}", vplexVolumeURI);
WorkflowStepCompleter.stepFailed(stepId, ie);
} catch (Exception e) {
_log.info("Exception attempting to validate the backend volumes for VPLEX volume {}", vplexVolumeURI);
ServiceCoded sc = DeviceControllerExceptions.vplex.failureValidatingVplexVolume(vplexVolumeURI.toString(), (vplexVolume != null ? vplexVolume.getLabel() : ""), e.getMessage());
WorkflowStepCompleter.stepFailed(stepId, sc);
}
}
use of com.emc.storageos.vplex.api.VPlexApiClient in project coprhd-controller by CoprHD.
the class VPlexDeviceController method getVPlexAPIClient.
private static VPlexApiClient getVPlexAPIClient(VPlexApiFactory vplexApiFactory, URI vplexUri, DbClient dbClient) throws URISyntaxException {
VPlexApiClient client = VPlexControllerUtils.getVPlexAPIClient(vplexApiFactory, vplexUri, dbClient);
updateTimeoutValues();
return client;
}
use of com.emc.storageos.vplex.api.VPlexApiClient in project coprhd-controller by CoprHD.
the class VPlexDeviceController method promoteMirror.
/**
* This method creates the virtual volume from the detached mirror device.
*
* @param vplexURI
* The vplex storage system URI
* @param vplexMirrorURI
* The URI of the vplex mirror that needs to be promoted to the virtual volume
* @param promoteVolumeURI
* The URI of the volume will be used as a promoted vplex volume
* @param stepId
* The worflow stepId
*
* @throws WorkflowException
* When an error occurs updating the workflow step
* state.
*/
public void promoteMirror(URI vplexURI, URI vplexMirrorURI, URI promoteVolumeURI, String stepId) throws WorkflowException {
try {
WorkflowStepCompleter.stepExecuting(stepId);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexURI, _dbClient);
VplexMirror vplexMirror = getDataObject(VplexMirror.class, vplexMirrorURI, _dbClient);
Volume sourceVplexVolume = getDataObject(Volume.class, vplexMirror.getSource().getURI(), _dbClient);
Volume promoteVolume = _dbClient.queryObject(Volume.class, promoteVolumeURI);
// Find virtual volume that should have been created when we did detach mirror.
// Virtual volume is created with the same name as the device name.
VPlexVirtualVolumeInfo vvInfo = client.findVirtualVolume(vplexMirror.getDeviceLabel(), null);
// Get the backend volume for this promoted VPLEX volume.
StringSet assocVolumes = vplexMirror.getAssociatedVolumes();
// Get the ViPR label for the promoted VPLEX volume.
String promotedLabel = String.format("%s-%s", sourceVplexVolume.getLabel(), vplexMirror.getLabel());
// Rename the vplex volume created using device detach mirror. If custom naming is enabled
// generate the custom name, else the name follows the default naming convention and must
// be renamed to append the "_vol" suffix.
String newVolumeName = null;
try {
if (CustomVolumeNamingUtils.isCustomVolumeNamingEnabled(customConfigHandler, DiscoveredDataObject.Type.vplex.name())) {
String customConfigName = CustomConfigConstants.CUSTOM_VOLUME_NAME;
Project project = _dbClient.queryObject(Project.class, promoteVolume.getProject().getURI());
TenantOrg tenant = _dbClient.queryObject(TenantOrg.class, promoteVolume.getTenant().getURI());
DataSource customNameDataSource = CustomVolumeNamingUtils.getCustomConfigDataSource(project, tenant, promotedLabel, vvInfo.getWwn(), null, dataSourceFactory, customConfigName, _dbClient);
if (customNameDataSource != null) {
newVolumeName = CustomVolumeNamingUtils.getCustomName(customConfigHandler, customConfigName, customNameDataSource, DiscoveredDataObject.Type.vplex.name());
}
// Rename the vplex volume created using device detach mirror,
vvInfo = CustomVolumeNamingUtils.renameVolumeOnVPlex(vvInfo, newVolumeName, client);
promotedLabel = newVolumeName;
} else {
// Build the name for volume so as to rename the vplex volume that is created
// with the same name as the device name to follow the name pattern _vol
// as the suffix for the vplex volumes
StringBuilder volumeNameBuilder = new StringBuilder();
volumeNameBuilder.append(vplexMirror.getDeviceLabel());
volumeNameBuilder.append(VPlexApiConstants.VIRTUAL_VOLUME_SUFFIX);
newVolumeName = volumeNameBuilder.toString();
// Rename the vplex volume created using device detach mirror,
vvInfo = CustomVolumeNamingUtils.renameVolumeOnVPlex(vvInfo, newVolumeName, client);
}
} catch (Exception e) {
_log.warn(String.format("Error renaming promoted VPLEX volume %s", promoteVolumeURI), e);
}
_log.info(String.format("Renamed promoted virtual volume: %s path: %s", vvInfo.getName(), vvInfo.getPath()));
// Fill in the details for the promoted vplex volume
promoteVolume.setLabel(promotedLabel);
promoteVolume.setNativeId(vvInfo.getPath());
promoteVolume.setNativeGuid(vvInfo.getPath());
promoteVolume.setDeviceLabel(vvInfo.getName());
promoteVolume.setThinlyProvisioned(vvInfo.isThinEnabled());
promoteVolume.setWWN(vvInfo.getWwn());
// For Vplex virtual volumes set allocated capacity to 0 (cop-18608)
promoteVolume.setAllocatedCapacity(0L);
promoteVolume.setCapacity(vplexMirror.getCapacity());
promoteVolume.setProvisionedCapacity(vplexMirror.getProvisionedCapacity());
promoteVolume.setVirtualPool(vplexMirror.getVirtualPool());
promoteVolume.setVirtualArray(vplexMirror.getVirtualArray());
promoteVolume.setStorageController(vplexMirror.getStorageController());
promoteVolume.setSystemType(DiscoveredDataObject.Type.vplex.name());
promoteVolume.setPool(NullColumnValueGetter.getNullURI());
promoteVolume.setAssociatedVolumes(new StringSet(assocVolumes));
promoteVolume.setThinlyProvisioned(vplexMirror.getThinlyProvisioned());
promoteVolume.setThinVolumePreAllocationSize(vplexMirror.getThinPreAllocationSize());
// VPLEX volumes created by VIPR have syncActive set to true hence setting same value for promoted vplex
// volumes
promoteVolume.setSyncActive(true);
// Also, we update the name portion of the project and tenant URIs
// to reflect the new 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 = promoteVolume.getProject();
namedURI.setName(promotedLabel);
promoteVolume.setProject(namedURI);
namedURI = promoteVolume.getTenant();
namedURI.setName(promotedLabel);
promoteVolume.setTenant(namedURI);
// Remove mirror from the source VPLEX volume
sourceVplexVolume.getMirrors().remove(vplexMirror.getId().toString());
_dbClient.updateObject(sourceVplexVolume);
// Delete the mirror object
_dbClient.removeObject(vplexMirror);
// Persist changes for the newly promoted volume
_dbClient.updateObject(promoteVolume);
WorkflowStepCompleter.stepSucceded(stepId);
} catch (VPlexApiException vae) {
_log.error("Exception promoting mirror volume: " + vae.getMessage(), vae);
WorkflowStepCompleter.stepFailed(stepId, vae);
} catch (Exception ex) {
_log.error("Exception promoting mirror volume: " + ex.getMessage(), ex);
ServiceError serviceError = VPlexApiException.errors.promoteMirrorFailed(ex);
WorkflowStepCompleter.stepFailed(stepId, serviceError);
}
}
use of com.emc.storageos.vplex.api.VPlexApiClient in project coprhd-controller by CoprHD.
the class VPlexDeviceController method deleteMigrationStep.
public void deleteMigrationStep(URI vplexURI, URI migrationURI, String stepId) {
WorkflowStepCompleter.stepExecuting(stepId);
try {
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
Migration migration = getDataObject(Migration.class, migrationURI, _dbClient);
client.removeMigrations(Arrays.asList(migration.getLabel()));
migration.setInactive(true);
_dbClient.updateObject(migration);
WorkflowStepCompleter.stepSucceded(stepId);
} catch (Exception ex) {
_log.error("Exception deleting migration:", ex);
String opName = ResourceOperationTypeEnum.DELETE_MIGRATION.getName();
ServiceError serviceError = VPlexApiException.errors.operateMigrationFailed(opName, ex);
WorkflowStepCompleter.stepFailed(stepId, serviceError);
}
}
use of com.emc.storageos.vplex.api.VPlexApiClient in project coprhd-controller by CoprHD.
the class VPlexDeviceController method deleteMirrorDevice.
/**
* Do the delete of a VPlex mirror device .
* This is called as a Workflow Step.
* NOTE: The parameters here must match deleteMirrorDeviceMethod above (except stepId).
*
* @param vplexURI
* URI of the VPlex StorageSystem
* @param vplexMirrorURI
* URI of the mirror to be deleted
* @param stepId
* The stepId used for completion.
*
* @throws WorkflowException
* When an error occurs updating the workflow step
* state.
*/
public void deleteMirrorDevice(URI vplexURI, URI vplexMirrorURI, String stepId) throws WorkflowException {
try {
WorkflowStepCompleter.stepExecuting(stepId);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexURI, _dbClient);
VplexMirror vplexMirror = getDataObject(VplexMirror.class, vplexMirrorURI, _dbClient);
if (vplexMirror.getDeviceLabel() != null) {
// Call to delete mirror device
client.deleteLocalDevice(vplexMirror.getDeviceLabel());
if (vplexMirror.getSource() != null && vplexMirror.getSource().getURI() != null) {
Volume vplexVolume = getDataObject(Volume.class, vplexMirror.getSource().getURI(), _dbClient);
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
updateThinProperty(client, vplexSystem, vplexVolume);
}
// Record VPLEX mirror delete event.
recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.DELETE_VOLUME_MIRROR.getEvType(true), Operation.Status.ready, OperationTypeEnum.DELETE_VOLUME_MIRROR.getDescription());
} else {
_log.info("It seems vplex mirror {} was never created, so just move to the next step.", vplexMirror.getLabel());
}
WorkflowStepCompleter.stepSucceded(stepId);
} catch (VPlexApiException vae) {
_log.error("Exception deleting VPlex Virtual Volume: " + vae.getMessage(), vae);
recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.DELETE_VOLUME_MIRROR.getEvType(true), Operation.Status.error, OperationTypeEnum.DELETE_VOLUME_MIRROR.getDescription());
WorkflowStepCompleter.stepFailed(stepId, vae);
} catch (Exception ex) {
_log.error("Exception deleting VPlex Virtual Volume: " + ex.getMessage(), ex);
String opName = ResourceOperationTypeEnum.DELETE_VPLEX_LOCAL_MIRROR.getName();
ServiceError serviceError = VPlexApiException.errors.deleteMirrorFailed(opName, ex);
recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.DELETE_VOLUME_MIRROR.getEvType(true), Operation.Status.error, OperationTypeEnum.DELETE_VOLUME_MIRROR.getDescription());
WorkflowStepCompleter.stepFailed(stepId, serviceError);
}
}
Aggregations