use of com.emc.storageos.db.client.model.VplexMirror in project coprhd-controller by CoprHD.
the class VPlexBlockServiceApiImpl method preparePromotedVolumes.
/**
* This method creates volume objects for the copiesToStop which will used as
* independent virtual volumes if detach mirror action completes successfully.
*/
private List<URI> preparePromotedVolumes(List<VplexMirror> copiesToStop, TaskList taskList, String opId) {
List<URI> promotedVolumes = new ArrayList<URI>();
for (VplexMirror copy : copiesToStop) {
Volume v = new Volume();
v.setId(URIUtil.createId(Volume.class));
Volume sourceVplexVolume = _dbClient.queryObject(Volume.class, copy.getSource());
String promotedLabel = String.format("%s-%s", sourceVplexVolume.getLabel(), copy.getLabel());
v.setProject(new NamedURI(copy.getProject().getURI(), promotedLabel));
StringSet protocols = new StringSet();
protocols.add(StorageProtocol.Block.FC.name());
v.setProtocol(protocols);
v.setTenant(new NamedURI(copy.getTenant().getURI(), promotedLabel));
_dbClient.createObject(v);
Operation op = _dbClient.createTaskOpStatus(Volume.class, v.getId(), opId, ResourceOperationTypeEnum.PROMOTE_COPY_TO_VPLEX, copy.getId().toString());
taskList.getTaskList().add(toTask(v, Arrays.asList(copy), opId, op));
promotedVolumes.add(v.getId());
}
return promotedVolumes;
}
use of com.emc.storageos.db.client.model.VplexMirror in project coprhd-controller by CoprHD.
the class VPlexBlockServiceApiImpl method changeVirtualArrayForVolumes.
/**
* {@inheritDoc}
*/
@Override
public void changeVirtualArrayForVolumes(List<Volume> volumes, BlockConsistencyGroup cg, List<Volume> cgVolumes, VirtualArray newVirtualArray, String taskId) throws InternalException {
// if they remove the snapshots, they can perform the varray change.
for (Volume volume : volumes) {
List<BlockSnapshot> snapshots = getSnapshots(volume);
if (!snapshots.isEmpty()) {
for (BlockSnapshot snapshot : snapshots) {
if (!snapshot.getInactive()) {
throw APIException.badRequests.volumeForVarrayChangeHasSnaps(volume.getId().toString());
}
}
}
// If the volume has mirrors then varray change will not
// be allowed. User needs to explicitly delete mirrors first.
// This is applicable for both Local and Distributed volumes.
// For distributed volume getMirrors will get mirror if any
// on source or HA side.
StringSet mirrorURIs = volume.getMirrors();
if (mirrorURIs != null && !mirrorURIs.isEmpty()) {
List<VplexMirror> mirrors = _dbClient.queryObject(VplexMirror.class, StringSetUtil.stringSetToUriList(mirrorURIs));
if (mirrors != null && !mirrors.isEmpty()) {
throw APIException.badRequests.volumeForVarrayChangeHasMirrors(volume.getId().toString(), volume.getLabel());
}
}
}
// vpool change.
if ((cg != null) && (volumes.size() > _maxCgVolumesForMigration)) {
throw APIException.badRequests.cgContainsTooManyVolumesForVArrayChange(cg.getLabel(), volumes.size(), _maxCgVolumesForMigration);
}
// we don't allow the varray change.
if ((cg != null) && (cg.checkForType(Types.LOCAL)) && (cgVolumes.size() > 1)) {
verifyTargetSystemsForCGDataMigration(volumes, null, newVirtualArray.getId());
}
// Create the volume descriptors for the virtual array change.
List<VolumeDescriptor> descriptors = createVolumeDescriptorsForVarrayChange(volumes, newVirtualArray, taskId);
try {
// Orchestrate the virtual array change.
BlockOrchestrationController controller = getController(BlockOrchestrationController.class, BlockOrchestrationController.BLOCK_ORCHESTRATION_DEVICE);
controller.changeVirtualArray(descriptors, taskId);
s_logger.info("Successfully invoked block orchestrator.");
} catch (InternalException e) {
s_logger.error("Controller error", e);
for (VolumeDescriptor descriptor : descriptors) {
// migration targets and migrations.
if (VolumeDescriptor.Type.VPLEX_MIGRATE_VOLUME.equals(descriptor.getType())) {
_dbClient.error(Volume.class, descriptor.getVolumeURI(), taskId, e);
_dbClient.error(Migration.class, descriptor.getMigrationId(), taskId, e);
}
}
throw e;
}
}
use of com.emc.storageos.db.client.model.VplexMirror in project coprhd-controller by CoprHD.
the class VPlexBlockServiceApiImpl method updateBackendVolumeToMirrorVpoolMap.
/**
* Convenience method to update backendVolumeToMirrorVpoolMap for the VPLEX Distributed volume.
* In case if there is already mirror for the vplex volume, this method ensures
* to add entry to the map only if there isn't already mirror on either leg.
*
* @param vplexVolume The reference to vplex distributed volume
* @param associatedVolumeIds URIs of the associated volumes
* @param sourceVirtualPool The reference to virtual pool to which vplex volume is associated with
* @param sourceMirrorVPool The reference to virtual pool for the mirror on the source side
* @param haMirrorVPool The reference to virtual pool for the mirror on the HA side
* @param backendVolumeToMirrorVpoolMap OUT param containing map of backend volume to mirror vpool
*/
private void updateBackendVolumeToMirrorVpoolMap(Volume vplexVolume, StringSet associatedVolumeIds, VirtualPool sourceVirtualPool, VirtualPool sourceMirrorVPool, VirtualPool haMirrorVPool, Map<Volume, VirtualPool> backendVolumeToMirrorVpoolMap) {
Set<String> vplexClusterWithMirrorForVolume = new HashSet<String>();
// Set vplexClusterWithMirrorForVolume contains Vplex Cluster on which mirror already exist for the vplex volume
if (vplexVolume.getMirrors() != null && !vplexVolume.getMirrors().isEmpty()) {
StringSet existingMirrors = vplexVolume.getMirrors();
for (String existingMirrorURI : existingMirrors) {
VplexMirror existingMirror = _dbClient.queryObject(VplexMirror.class, URI.create(existingMirrorURI));
if (existingMirror != null && !existingMirror.getInactive()) {
String cluster = ConnectivityUtil.getVplexClusterForVarray(existingMirror.getVirtualArray(), vplexVolume.getStorageController(), _dbClient);
checkIfClusterIsUnknown(cluster, existingMirror.getVirtualArray().toString(), vplexVolume.getStorageController().toString());
vplexClusterWithMirrorForVolume.add(cluster);
}
}
s_logger.info("Vplex Mirror(s) already exists for Vplex volume" + vplexVolume.getLabel() + " " + vplexVolume.getId() + " on cluster " + vplexClusterWithMirrorForVolume);
}
for (String associatedVolumeId : associatedVolumeIds) {
if (sourceMirrorVPool != null && sourceVirtualPool.getMaxNativeContinuousCopies() > 0) {
// Get the source backend volume
Volume associatedVolume = VPlexUtil.getVPLEXBackendVolume(vplexVolume, true, _dbClient);
if (associatedVolume != null && associatedVolume.getId().toString().equals(associatedVolumeId)) {
if (!vplexClusterWithMirrorForVolume.isEmpty()) {
// Get the vplex cluster for the source varray
String cluster = ConnectivityUtil.getVplexClusterForVarray(vplexVolume.getVirtualArray(), vplexVolume.getStorageController(), _dbClient);
checkIfClusterIsUnknown(cluster, vplexVolume.getVirtualArray().toString(), vplexVolume.getStorageController().toString());
// If there isn't already mirror on the source side then add entry to backendVolumeToMirrorVpoolMap
if (!vplexClusterWithMirrorForVolume.contains(cluster)) {
backendVolumeToMirrorVpoolMap.put(associatedVolume, sourceMirrorVPool);
}
} else {
backendVolumeToMirrorVpoolMap.put(associatedVolume, sourceMirrorVPool);
}
}
} else {
s_logger.info("The max native continuous copies for the source Vpool {} is {} ", sourceVirtualPool.getLabel(), sourceVirtualPool.getMaxNativeContinuousCopies());
if (sourceMirrorVPool == null) {
s_logger.info("The mirror will not be created on the source side as the source mirror pool is not provided " + "in the virtual pool {} {}", sourceVirtualPool.getLabel(), sourceVirtualPool.getId());
}
}
VirtualPool haVPool = VirtualPool.getHAVPool(sourceVirtualPool, _dbClient);
if (haMirrorVPool != null && haVPool != null && haVPool.getMaxNativeContinuousCopies() > 0) {
// Get the HA backend volume
Volume associatedVolume = VPlexUtil.getVPLEXBackendVolume(vplexVolume, false, _dbClient);
if (associatedVolume != null && associatedVolume.getId().toString().equals(associatedVolumeId)) {
if (!vplexClusterWithMirrorForVolume.isEmpty()) {
// Get HA varray
URI haVarrayURI = VPlexUtil.getHAVarray(sourceVirtualPool);
if (haVarrayURI != null) {
// Get the vplex cluster for the HA varray
String cluster = ConnectivityUtil.getVplexClusterForVarray(haVarrayURI, vplexVolume.getStorageController(), _dbClient);
checkIfClusterIsUnknown(cluster, haVarrayURI.toString(), vplexVolume.getStorageController().toString());
// If there isn't already mirror on the HA side then add entry to backendVolumeToMirrorVpoolMap
if (!vplexClusterWithMirrorForVolume.contains(cluster)) {
backendVolumeToMirrorVpoolMap.put(associatedVolume, haMirrorVPool);
}
}
} else {
backendVolumeToMirrorVpoolMap.put(associatedVolume, haMirrorVPool);
}
}
} else {
if (haVPool != null) {
s_logger.info("The max native continuous copies for the HA Vpool {} is {} ", haVPool.getLabel(), haVPool.getMaxNativeContinuousCopies());
if (haMirrorVPool == null) {
s_logger.info("The mirror will not be created on the HA side as the HA mirror pool is not provided " + "in the virtual pool {} {}", haVPool.getLabel(), haVPool.getId());
}
}
}
}
}
use of com.emc.storageos.db.client.model.VplexMirror in project coprhd-controller by CoprHD.
the class VplexMirrorDeactivateCompleter method complete.
@Override
protected void complete(DbClient dbClient, Operation.Status status, ServiceCoded coded) throws DeviceControllerException {
try {
super.complete(dbClient, status, coded);
VplexMirror mirror = dbClient.queryObject(VplexMirror.class, getMirrorURI());
Volume sourceVplexVolume = dbClient.queryObject(Volume.class, mirror.getSource());
switch(status) {
case error:
dbClient.error(VplexMirror.class, mirror.getId(), getOpId(), coded);
dbClient.error(Volume.class, sourceVplexVolume.getId(), getOpId(), coded);
break;
default:
_log.info("Removing mirror {} from source volume {}", mirror.getId().toString(), sourceVplexVolume.getId().toString());
sourceVplexVolume.getMirrors().remove(mirror.getId().toString());
dbClient.persistObject(sourceVplexVolume);
if (mirror.getAssociatedVolumes() != null && !mirror.getAssociatedVolumes().isEmpty()) {
for (String volumeUri : mirror.getAssociatedVolumes()) {
Volume assocVolume = dbClient.queryObject(Volume.class, URI.create(volumeUri));
if (assocVolume != null && !assocVolume.getInactive()) {
dbClient.markForDeletion(assocVolume);
}
}
}
dbClient.markForDeletion(mirror);
dbClient.ready(VplexMirror.class, mirror.getId(), getOpId());
dbClient.ready(Volume.class, sourceVplexVolume.getId(), getOpId());
}
recordVplexMirrorOperation(dbClient, OperationTypeEnum.DEACTIVATE_VOLUME_MIRROR, status, eventMessage(status, sourceVplexVolume, mirror), mirror, sourceVplexVolume);
} catch (Exception e) {
_log.error("Failed updating status. VplexMirrorDeactivate {}, for task " + getOpId(), getId(), e);
}
}
use of com.emc.storageos.db.client.model.VplexMirror in project coprhd-controller by CoprHD.
the class VplexVolumeValidator method validateStorageVolumes.
/**
* Validates either storage volumes for either distributed or local vplex volumes.
*
* @param virtualVolume
* -- Vplex virtual volume
* @param volumeId
* -- identification for log
* @param topLevelDeviceName
* -- top level VPLEX device name
* @param distributed
* -- if true VPLEX distributed, false if VPLEX local
* @param cluster
* cluster-1 or cluster-2
* @param hasMirror
* -- if true this cluster has a mirror
* @return failed -- If true a discrepancy was detected
*/
private boolean validateStorageVolumes(Volume virtualVolume, String volumeId, String topLevelDeviceName, boolean distributed, String cluster, boolean hasMirror) {
boolean failed = false;
Map<String, VPlexStorageVolumeInfo> wwnToStorageVolumeInfos = client.getStorageVolumeInfoForDevice(topLevelDeviceName, distributed ? VPlexApiConstants.DISTRIBUTED_VIRTUAL_VOLUME : VPlexApiConstants.LOCAL_VIRTUAL_VOLUME, cluster, hasMirror);
// Check local volume is present
Volume assocVolume = VPlexUtil.getVPLEXBackendVolume(virtualVolume, true, getDbClient());
if (!storageSystemSupportsValidation(assocVolume)) {
return failed;
}
if (!wwnToStorageVolumeInfos.keySet().contains(assocVolume.getWWN())) {
getValidatorLogger().logDiff(volumeId, "SOURCE storage volume WWN", assocVolume.getWWN(), wwnToStorageVolumeInfos.keySet().toString());
failed = true;
} else {
wwnToStorageVolumeInfos.remove(assocVolume.getWWN());
}
// Check HA volume is present
if (distributed) {
assocVolume = VPlexUtil.getVPLEXBackendVolume(virtualVolume, false, getDbClient());
if (!storageSystemSupportsValidation(assocVolume)) {
return failed;
}
if (!wwnToStorageVolumeInfos.keySet().contains(assocVolume.getWWN())) {
getValidatorLogger().logDiff(volumeId, "HA storage volume WWN", assocVolume.getWWN(), wwnToStorageVolumeInfos.keySet().toString());
failed = true;
} else {
wwnToStorageVolumeInfos.remove(assocVolume.getWWN());
}
}
// Process any mirrors that were found
if (virtualVolume.getMirrors() != null) {
for (String mirrorId : virtualVolume.getMirrors()) {
VplexMirror mirror = getDbClient().queryObject(VplexMirror.class, URI.create(mirrorId));
if (mirror == null || mirror.getInactive() || mirror.getAssociatedVolumes() == null) {
// Not fully formed for some reason, skip it
continue;
}
// Now get the underlying Storage Volume
for (String mirrorAssociatedId : mirror.getAssociatedVolumes()) {
Volume mirrorVolume = getDbClient().queryObject(Volume.class, URI.create(mirrorAssociatedId));
if (!storageSystemSupportsValidation(mirrorVolume)) {
return failed;
}
if (mirrorVolume != null && !NullColumnValueGetter.isNullValue(mirrorVolume.getWWN())) {
if (!wwnToStorageVolumeInfos.keySet().contains(mirrorVolume.getWWN())) {
getValidatorLogger().logDiff(volumeId, "Mirror WWN", mirrorVolume.getWWN(), wwnToStorageVolumeInfos.keySet().toString());
failed = true;
} else {
wwnToStorageVolumeInfos.remove(mirrorVolume.getWWN());
}
}
}
}
}
if (!wwnToStorageVolumeInfos.isEmpty()) {
getValidatorLogger().logDiff(volumeId, "Extra storage volumes found", ValidatorLogger.NO_MATCHING_ENTRY, wwnToStorageVolumeInfos.keySet().toString());
failed = true;
}
return failed;
}
Aggregations