use of com.emc.storageos.db.client.model.RemoteDirectorGroup in project coprhd-controller by CoprHD.
the class SRDFBlockServiceApiImpl method prepareRecommendedVolumes.
/**
* Prepare Recommended Volumes for SRDF scenarios only.
*
* This method is responsible for acting the same as the unprotected "prepareRecommendedVolumes"
* call, however it needs to create multiple volumes per single volume requests in order to
* generate SRDF protection.
*
* Those most typical scenario is, that for any one volume requested in an SRDF configuration,
* we create: 1. One Source Volume 3. One Target Volume on target varrays
*
* @param param
* volume create request
* @param task
* task from request or generated
* @param taskList
* task list
* @param project
* project from request
* @param varray
* varray from request
* @param vpool
* vpool from request
* @param volumeCount
* volume count from the request
* @param recommendations
* list of resulting recommendations from placement
* @param consistencyGroup
* consistency group ID
* @return list of volume URIs created
*/
private List<URI> prepareRecommendedVolumes(final String task, final TaskList taskList, final Project project, final VirtualArray varray, final VirtualPool vpool, final Integer volumeCount, final List<Recommendation> recommendations, final BlockConsistencyGroup consistencyGroup, final String volumeLabel, final String size) {
List<URI> volumeURIs = new ArrayList<URI>();
try {
// Create an entire Protection object for each recommendation result.
Iterator<Recommendation> recommendationsIter = recommendations.iterator();
while (recommendationsIter.hasNext()) {
SRDFRecommendation recommendation = (SRDFRecommendation) recommendationsIter.next();
// until we (later) fix creating volumes while in SWAPPED state.
for (SRDFRecommendation.Target target : recommendation.getVirtualArrayTargetMap().values()) {
if (target != null && SRDFScheduler.rdfGroupHasSwappedVolumes(_dbClient, project.getId(), target.getSourceRAGroup())) {
RemoteDirectorGroup rdg = _dbClient.queryObject(RemoteDirectorGroup.class, target.getSourceRAGroup());
throw BadRequestException.badRequests.cannotAddVolumesToSwappedReplicationGroup(rdg.getLabel());
}
}
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, recommendation.getSourceStorageSystem());
// operation for each volume to be created.
for (int i = 0; i < volumeCount; i++) {
// get generated volume name
String newVolumeLabel = generateDefaultVolumeLabel(volumeLabel, i, volumeCount);
// Grab the existing volume and task object from the incoming task list
Volume srcVolume = StorageScheduler.getPrecreatedVolume(_dbClient, taskList, newVolumeLabel);
boolean volumePrecreated = false;
if (srcVolume != null) {
volumePrecreated = true;
}
// number of targets.
if (recommendation.getVpoolChangeVolume() == null) {
srcVolume = prepareVolume(srcVolume, project, varray, vpool, size, recommendation, newVolumeLabel, consistencyGroup, task, false, Volume.PersonalityTypes.SOURCE, null, null, null);
volumeURIs.add(srcVolume.getId());
if (!volumePrecreated) {
taskList.getTaskList().add(toTask(srcVolume, task));
}
} else {
srcVolume = _dbClient.queryObject(Volume.class, recommendation.getVpoolChangeVolume());
Operation op = _dbClient.createTaskOpStatus(Volume.class, srcVolume.getId(), task, ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME);
// Fill in additional information that prepare would've filled in that's specific to SRDF.
// Best to only fill in information here that isn't harmful if a rollback occurred,
// and the protection never got set up.
volumeURIs.add(srcVolume.getId());
taskList.getTaskList().add(toTask(srcVolume, task, op));
}
// Remove "-source" designation in the label if found
if (newVolumeLabel.contains("-source")) {
newVolumeLabel = newVolumeLabel.replaceAll("-source", "");
}
Map<URI, VpoolRemoteCopyProtectionSettings> settingMap = VirtualPool.getRemoteProtectionSettings(vpool, _dbClient);
for (VirtualArray protectionVirtualArray : SRDFScheduler.getTargetVirtualArraysForVirtualPool(project, vpool, _dbClient, _permissionsHelper)) {
VpoolRemoteCopyProtectionSettings settings = settingMap.get(protectionVirtualArray.getId());
// COP-16363 Create target BCG in controllersvc
// Prepare and populate CG request for the SRDF targets
volumeURIs.addAll(prepareTargetVolumes(project, vpool, recommendation, new StringBuilder(newVolumeLabel), protectionVirtualArray, settings, srcVolume, task, taskList, size));
}
}
}
} catch (InternalException e) {
_log.error("Rolling back the created CGs if any.");
throw e;
} catch (BadRequestException e) {
_log.info("Bad request exception: " + e.getMessage());
throw e;
} catch (Exception e) {
_log.error("Rolling back the created CGs if any.");
throw APIException.badRequests.srdfInternalError(e);
}
return volumeURIs;
}
use of com.emc.storageos.db.client.model.RemoteDirectorGroup in project coprhd-controller by CoprHD.
the class StorageSystemService method getRDFGroup.
/**
* Get RDF Group
*
* @param id
* @param rdfGroupId
* @brief Show details about an RDF group
* @return
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/rdf-groups/{rdfGrpId}")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public RDFGroupRestRep getRDFGroup(@PathParam("id") URI id, @PathParam("rdfGrpId") URI rdfGroupId) {
// Make sure storage system is registered.
ArgValidator.checkFieldUriType(id, StorageSystem.class, "id");
StorageSystem system = queryResource(id);
ArgValidator.checkEntity(system, id, isIdEmbeddedInURL(id));
ArgValidator.checkFieldUriType(rdfGroupId, RemoteDirectorGroup.class, "rdfGrpId");
RemoteDirectorGroup raGroup = _dbClient.queryObject(RemoteDirectorGroup.class, rdfGroupId);
ArgValidator.checkEntity(raGroup, rdfGroupId, isIdEmbeddedInURL(rdfGroupId));
return toRDFGroupRep(raGroup, _dbClient, _coordinator);
}
use of com.emc.storageos.db.client.model.RemoteDirectorGroup in project coprhd-controller by CoprHD.
the class BlockRemoteReplicationIngestOrchestrator method validateUnManagedVolumeProperties.
/**
* Validates the UnManagedVolume SRDF Properties.
*
* @param unManagedVolume
* @param virtualArray
* @param virtualPool
*/
private void validateUnManagedVolumeProperties(UnManagedVolume unManagedVolume, VirtualArray virtualArray, VirtualPool virtualPool, Project project) {
StringSetMap unManagedVolumeInformation = unManagedVolume.getVolumeInformation();
URI rdfGroupId = getRDFGroupBasedOnPersonality(unManagedVolumeInformation);
// To make sure rdfGroup is populated for both R1 & R2 volumes.
if (null == rdfGroupId) {
_logger.warn("SRDF Volume ingestion failed for unmanagedVolume {} as not able to find RDFGroup.", unManagedVolume.getNativeGuid());
throw IngestionException.exceptions.unmanagedVolumeRDFGroupMissing(unManagedVolume.getNativeGuid());
}
RemoteDirectorGroup rdfGroup = _dbClient.queryObject(RemoteDirectorGroup.class, rdfGroupId);
// name check, "V-<projectname>" or "<projectname>"
StringSet grpNames = SRDFUtils.getQualifyingRDFGroupNames(project);
// Validate the project Name with the unmanaged volume rdfGroup name.
if (null == rdfGroup.getLabel() || !SRDFUtils.containsRaGroupName(grpNames, rdfGroup.getLabel())) {
_logger.warn("SRDF Volume ingestion failed for unmanagedVolume {} due to mismatch in RDF group name", unManagedVolume.getNativeGuid());
throw IngestionException.exceptions.unmanagedVolumeRDFGroupMismatch(unManagedVolume.getNativeGuid(), rdfGroup.getLabel(), project.getLabel(), StringUtils.join(grpNames, ","));
}
String type = PropertySetterUtil.extractValueFromStringSet(SupportedVolumeInformation.REMOTE_VOLUME_TYPE.toString(), unManagedVolumeInformation);
if (null == type) {
_logger.warn("SRDF Volume ingestion failed for unmanagedVolume {}", unManagedVolume.getNativeGuid());
throw IngestionException.exceptions.unmanagedVolumeVolumeTypeNotSet(unManagedVolume.getNativeGuid());
}
_logger.info("Type {} Source Native Guid {}", type, unManagedVolume.getNativeGuid());
if (RemoteMirrorObject.Types.SOURCE.toString().equalsIgnoreCase(type)) {
validateSourceVolumeVarrayWithTargetVPool(unManagedVolume, virtualPool);
} else if (RemoteMirrorObject.Types.TARGET.toString().equalsIgnoreCase(type)) {
validateTargetVolumeVpoolWithSourceVolume(unManagedVolume, virtualArray);
}
}
use of com.emc.storageos.db.client.model.RemoteDirectorGroup in project coprhd-controller by CoprHD.
the class SRDFDeviceController method createSrdfCGPairStepsOnPopulatedGroup.
private String createSrdfCGPairStepsOnPopulatedGroup(Volume source, String waitFor, Workflow workflow) {
List<URI> sourceURIs = new ArrayList<URI>();
sourceURIs.add(source.getId());
StorageSystem system = null;
String stepId = waitFor;
RemoteDirectorGroup group = null;
StringSet srdfTargets = source.getSrdfTargets();
if (null == srdfTargets) {
return waitFor;
}
List<URI> targetURIS = new ArrayList<URI>();
for (String targetStr : srdfTargets) {
/* 1. Create Element Replicas for each source/target pairing */
URI targetURI = URI.create(targetStr);
targetURIS.add(targetURI);
Volume target = dbClient.queryObject(Volume.class, targetURI);
group = dbClient.queryObject(RemoteDirectorGroup.class, target.getSrdfGroup());
system = dbClient.queryObject(StorageSystem.class, group.getSourceStorageSystemUri());
Workflow.Method createMethod = createSRDFVolumePairMethod(system.getId(), source.getId(), targetURI, null);
Workflow.Method rollbackMethod = rollbackSRDFLinkMethod(system.getId(), source.getId(), targetURI, false);
stepId = workflow.createStep(CREATE_SRDF_SYNC_VOLUME_PAIR_STEP_GROUP, CREATE_SRDF_SYNC_VOLUME_PAIR_STEP_DESC, stepId, system.getId(), system.getSystemType(), getClass(), createMethod, rollbackMethod, null);
}
/* 2. Invoke AddSyncpair with the created StorageSynchronized from Step 1 */
Workflow.Method addMethod = addVolumePairsToCgMethod(system.getId(), sourceURIs, group.getId(), null);
Workflow.Method rollbackAddMethod = rollbackAddSyncVolumePairMethod(system.getId(), sourceURIs, targetURIS, false);
workflow.createStep(CREATE_SRDF_MIRRORS_STEP_GROUP, CREATE_SRDF_MIRRORS_STEP_DESC, CREATE_SRDF_SYNC_VOLUME_PAIR_STEP_GROUP, system.getId(), system.getSystemType(), getClass(), addMethod, rollbackAddMethod, null);
return CREATE_SRDF_MIRRORS_STEP_GROUP;
}
use of com.emc.storageos.db.client.model.RemoteDirectorGroup in project coprhd-controller by CoprHD.
the class SRDFDeviceController method deleteSRDFMirrorSteps.
/**
* Deletion of SRDF Volumes with/without CGs.
*
* @param workflow
* @param waitFor
* @param sourceDescriptors
* @return
*/
private String deleteSRDFMirrorSteps(final Workflow workflow, String waitFor, final List<VolumeDescriptor> sourceDescriptors) {
log.info("START delete SRDF mirrors workflow");
Map<URI, Volume> sourcesVolumeMap = queryVolumes(sourceDescriptors);
StorageSystem system = null;
StorageSystem targetSystem = null;
List<URI> targetVolumeURIs = new ArrayList<URI>();
/**
* Locks that must be acquired before continuing.
*/
acquireWorkflowLockOrThrow(workflow, generateLocks(sourceDescriptors, sourcesVolumeMap));
if (canRemoveSrdfCg(sourcesVolumeMap)) {
// invoke workflow to delete CG
log.info("Invoking SRDF Consistency Group Deletion with all its volumes");
return deleteAllSrdfVolumesInCG(sourcesVolumeMap, workflow, waitFor, sourceDescriptors);
}
Map<URI, RemoteDirectorGroup> srdfGroupMap = new HashMap<URI, RemoteDirectorGroup>();
Map<URI, List<URI>> srdfGroupToSourceVolumeMap = new HashMap<URI, List<URI>>();
Map<URI, List<URI>> srdfGroupToTargetVolumeMap = new HashMap<URI, List<URI>>();
Map<URI, String> srdfGroupToTargetVolumeAccessState = new HashMap<URI, String>();
Map<URI, String> srdfGroupToLastWaitFor = new HashMap<URI, String>();
// invoke deletion of volume within CG
for (Volume source : sourcesVolumeMap.values()) {
StringSet srdfTargets = source.getSrdfTargets();
for (String srdfTarget : srdfTargets) {
log.info("suspend and detach: source:{}, target:{}", source.getId(), srdfTarget);
URI targetURI = URI.create(srdfTarget);
Volume target = dbClient.queryObject(Volume.class, targetURI);
if (null == target) {
log.warn("Target volume {} not available for SRDF source vol {}", source.getId(), targetURI);
// We need to proceed with the operation, as it could be because of a left over from last operation.
return waitFor;
}
log.info("target Volume {} with srdf group {}", target.getNativeGuid(), target.getSrdfGroup());
RemoteDirectorGroup group = dbClient.queryObject(RemoteDirectorGroup.class, target.getSrdfGroup());
system = dbClient.queryObject(StorageSystem.class, group.getSourceStorageSystemUri());
targetSystem = dbClient.queryObject(StorageSystem.class, group.getRemoteStorageSystemUri());
boolean activeMode = target.getSrdfCopyMode() != null && target.getSrdfCopyMode().equals(Mode.ACTIVE.toString());
boolean consExempt = true;
if (activeMode) {
consExempt = false;
}
if (!source.hasConsistencyGroup()) {
// No CG, so suspend single link
// Procedure:
// For SYNC/ASYNC pairs, we need to a) suspend the pairs (cons_exempt used in case of Asynchronous)
// and b)Detach the pairs.
// For ACTIVE pairs, we need to a) Suspend all the pairs in the Project/ RDF Group
// b) Detach the pairs and c)Resume the remaining pairs of the Project/ RDF Group .
Workflow.Method suspendMethod = suspendSRDFLinkMethod(system.getId(), source.getId(), targetURI, consExempt);
String suspendStep = workflow.createStep(DELETE_SRDF_MIRRORS_STEP_GROUP, SUSPEND_SRDF_MIRRORS_STEP_DESC, waitFor, system.getId(), system.getSystemType(), getClass(), suspendMethod, null, null);
// Second we detach the mirrors...
Workflow.Method detachMethod = detachVolumePairMethod(system.getId(), source.getId(), targetURI);
String detachStep = workflow.createStep(DELETE_SRDF_MIRRORS_STEP_GROUP, DETACH_SRDF_MIRRORS_STEP_DESC, suspendStep, system.getId(), system.getSystemType(), getClass(), detachMethod, null, null);
waitFor = detachStep;
if (activeMode) {
// We need to fill up necessary maps to be able to call Resume once on the SRDF
// group when all the requested volumes are removed from the SRDF group.
URI groupId = group.getId();
srdfGroupMap.put(groupId, group);
if (srdfGroupToSourceVolumeMap.get(groupId) == null) {
srdfGroupToSourceVolumeMap.put(groupId, new ArrayList<URI>());
}
if (srdfGroupToTargetVolumeMap.get(groupId) == null) {
srdfGroupToTargetVolumeMap.put(groupId, new ArrayList<URI>());
}
srdfGroupToSourceVolumeMap.get(groupId).add(source.getId());
srdfGroupToTargetVolumeMap.get(groupId).add(targetURI);
srdfGroupToLastWaitFor.put(groupId, waitFor);
srdfGroupToTargetVolumeAccessState.put(groupId, target.getAccessState());
}
} else {
// Defensive steps to prevent orphaned SRDF Volumes, which cannot be deleted.
targetVolumeURIs.add(targetURI);
// Procedure:
// For SYNC/ASYNC pairs, we need to a) remove the pairs from the Group, b) suspend the pairs
// and c)Detach the pairs.
// For ACTIVE pairs, we need to a) Suspend all the pairs in the CG, b) Remove the pairs from the Group
// c) Detach the pairs and d)Resume the remaining pairs of the Group.
// Keep the methods handy
Workflow.Method suspendPairMethod = suspendSRDFGroupLinkMethod(system.getId(), source.getId(), targetURI, consExempt);
Workflow.Method resumePairMethod = resumeGroupPairsMethod(system.getId(), source.getId(), targetURI);
if (activeMode) {
// suspend the Active pair
waitFor = workflow.createStep(DELETE_SRDF_MIRRORS_STEP_GROUP, SUSPEND_SRDF_MIRRORS_STEP_DESC, waitFor, system.getId(), system.getSystemType(), getClass(), suspendPairMethod, resumePairMethod, null);
}
Workflow.Method removePairFromGroupMethod = removePairFromGroup(system.getId(), source.getId(), targetURI, true);
String removePairFromGroupWorkflowDesc = String.format(REMOVE_SRDF_PAIR_STEP_DESC, target.getSrdfCopyMode());
waitFor = workflow.createStep(DELETE_SRDF_MIRRORS_STEP_GROUP, removePairFromGroupWorkflowDesc, waitFor, system.getId(), system.getSystemType(), getClass(), removePairFromGroupMethod, rollbackMethodNullMethod(), null);
if (!activeMode) {
Workflow.Method suspendMethod = suspendSRDFLinkMethod(system.getId(), source.getId(), targetURI, consExempt);
waitFor = workflow.createStep(DELETE_SRDF_MIRRORS_STEP_GROUP, SUSPEND_SRDF_MIRRORS_STEP_DESC, waitFor, system.getId(), system.getSystemType(), getClass(), suspendMethod, null, null);
}
// We now detach the active p...
// don't proceed if detach fails, earlier we were allowing the delete operation
// to proceed even if there is a failure on detach.
String detachVolumePairWorkflowDesc = String.format(DETACH_SRDF_PAIR_STEP_DESC, target.getSrdfCopyMode());
Workflow.Method detachPairMethod = detachVolumePairMethod(system.getId(), source.getId(), targetURI);
waitFor = workflow.createStep(DELETE_SRDF_MIRRORS_STEP_GROUP, detachVolumePairWorkflowDesc, waitFor, system.getId(), system.getSystemType(), getClass(), detachPairMethod, rollbackMethodNullMethod(), null);
if (activeMode) {
// Now resume the remaining active pairs..
waitFor = workflow.createStep(RESUME_SRDF_MIRRORS_STEP_GROUP, RESUME_SRDF_MIRRORS_STEP_DESC, waitFor, system.getId(), system.getSystemType(), getClass(), resumePairMethod, rollbackMethodNullMethod(), null);
}
}
}
}
String lastDeleteSRDFMirrorStep = waitFor;
if (!srdfGroupMap.isEmpty()) {
// Add step to resume each Active SRDF group
for (URI srdfGroupURI : srdfGroupMap.keySet()) {
RemoteDirectorGroup group = srdfGroupMap.get(srdfGroupURI);
if (srdfGroupToTargetVolumeAccessState.get(srdfGroupURI).equals(Volume.VolumeAccessState.NOT_READY.name())) {
log.info("Srdf group {} {} was already in a suspended state hence skipping resume on this group.", srdfGroupURI, group.getNativeGuid());
continue;
}
List<URI> sourceVolumes = srdfGroupToSourceVolumeMap.get(srdfGroupURI);
List<URI> targetVolumes = srdfGroupToTargetVolumeMap.get(srdfGroupURI);
String lastWaitFor = srdfGroupToLastWaitFor.get(srdfGroupURI);
system = dbClient.queryObject(StorageSystem.class, group.getSourceStorageSystemUri());
Workflow.Method resumeSRDFGroupMethod = resumeSRDFGroupMethod(system.getId(), group, sourceVolumes, targetVolumes);
lastDeleteSRDFMirrorStep = workflow.createStep(DELETE_SRDF_MIRRORS_STEP_GROUP, RESUME_SRDF_MIRRORS_STEP_DESC, lastWaitFor, system.getId(), system.getSystemType(), getClass(), resumeSRDFGroupMethod, null, null);
}
}
// refresh provider before invoking deleteVolume call
if (null != targetSystem) {
addStepToRefreshSystem(DELETE_SRDF_MIRRORS_STEP_GROUP, targetSystem, targetVolumeURIs, lastDeleteSRDFMirrorStep, workflow);
}
return DELETE_SRDF_MIRRORS_STEP_GROUP;
}
Aggregations