use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class RPBlockServiceApiImpl method upgradeToProtectedVolume.
/**
* Upgrade a local block volume to a protected RP volume
*
* @param changeVpoolVolume the existing volume being protected.
* @param newVpool the requested virtual pool
* @param vpoolChangeParam Param sent down by the API Service
* @param taskId the task identifier
* @throws InternalException
*/
private void upgradeToProtectedVolume(Volume changeVpoolVolume, VirtualPool newVpool, VirtualPoolChangeParam vpoolChangeParam, String taskId) throws InternalException {
Project project = _dbClient.queryObject(Project.class, changeVpoolVolume.getProject());
if (VirtualPool.vPoolSpecifiesProtection(newVpool)) {
// the volume from the existing CG before they can proceed.
if (!NullColumnValueGetter.isNullURI(changeVpoolVolume.getConsistencyGroup())) {
BlockConsistencyGroup cg = _dbClient.queryObject(BlockConsistencyGroup.class, changeVpoolVolume.getConsistencyGroup());
throw APIException.badRequests.cannotCreateRPVolumesInCG(changeVpoolVolume.getLabel(), cg.getLabel());
}
// The user needs to specify a CG for this operation.
if (vpoolChangeParam.getConsistencyGroup() == null) {
throw APIException.badRequests.addRecoverPointProtectionRequiresCG();
}
if (!CollectionUtils.isEmpty(getSnapshotsForVolume(changeVpoolVolume))) {
throw APIException.badRequests.cannotAddProtectionWhenSnapshotsExist(changeVpoolVolume.getLabel());
}
}
VirtualPoolCapabilityValuesWrapper capabilities = new VirtualPoolCapabilityValuesWrapper();
capabilities.put(VirtualPoolCapabilityValuesWrapper.SIZE, changeVpoolVolume.getCapacity());
capabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, 1);
capabilities.put(VirtualPoolCapabilityValuesWrapper.BLOCK_CONSISTENCY_GROUP, vpoolChangeParam.getConsistencyGroup());
capabilities.put(VirtualPoolCapabilityValuesWrapper.CHANGE_VPOOL_VOLUME, changeVpoolVolume.getId().toString());
List<Recommendation> recommendations = getRecommendationsForVirtualPoolChangeRequest(changeVpoolVolume, newVpool, vpoolChangeParam, capabilities);
if (recommendations.isEmpty()) {
throw APIException.badRequests.noStorageFoundForVolume();
}
// Get the volume's varray
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, changeVpoolVolume.getVirtualArray());
// Generate a VolumeCreate object that contains the information that createVolumes likes to consume.
VolumeCreate param = new VolumeCreate(changeVpoolVolume.getLabel(), String.valueOf(changeVpoolVolume.getCapacity()), 1, newVpool.getId(), changeVpoolVolume.getVirtualArray(), changeVpoolVolume.getProject().getURI());
TaskList taskList = new TaskList();
createTaskForVolume(changeVpoolVolume, ResourceOperationTypeEnum.CHANGE_BLOCK_VOLUME_VPOOL, taskList, taskId);
Map<VpoolUse, List<Recommendation>> recommendationMap = new HashMap<VpoolUse, List<Recommendation>>();
recommendationMap.put(VpoolUse.ROOT, recommendations);
createVolumes(param, project, varray, newVpool, recommendationMap, taskList, taskId, capabilities);
}
use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class RPBlockServiceApiImpl method addJournalCapacity.
/**
* Add additional journal volume(s) to an existing recoverpoint
* consistency group copy
*
* @param param - journal volume(s) creation parameters
* @param project - the project
* @param journalVarray - the virtual array for the journal(s)
* @param journalVpool - the virtual pool for the journal(s)
* @param consistencyGroup - the recoverpoint consistency group
* @param capabilities - parameters for the journal volume(s)
* @param task - the task identifier
* @return TaskList
*/
public TaskList addJournalCapacity(VolumeCreate param, Project project, VirtualArray journalVarray, VirtualPool journalVpool, BlockConsistencyGroup consistencyGroup, VirtualPoolCapabilityValuesWrapper capabilities, String task) {
ProtectionSystem protectionSystem = getBlockScheduler().getCgProtectionSystem(consistencyGroup.getId());
if (protectionSystem != null) {
_log.info("Narrowing down placement to use protection system {}, which is currently used by RecoverPoint consistency group {}.", protectionSystem.getLabel(), consistencyGroup);
} else {
throw APIException.badRequests.noProtectionSystemAssociatedWithTheCG(consistencyGroup.getId().toString());
}
// copy name to add the journal volume to
String copyName = param.getName();
// rp cluster internal site name of the copy
String internalSiteName = null;
// adding journal to a source copy
boolean isSource = false;
// adding journal to a target copy
boolean isTarget = false;
// adding journal to a metropoint standby copy
boolean isMPStandby = copyName.contains("Standby");
// get the list of source and target volumes; for metropoint, source volumes include both sides of the source
// metro volume
List<Volume> sourceVolumes = RPHelper.getCgSourceVolumes(consistencyGroup.getId(), _dbClient);
if (sourceVolumes.isEmpty()) {
throw APIException.badRequests.noSourceVolumesInCG(consistencyGroup.getLabel());
}
// only need one source volume to set up parameters for the operation
Volume firstSrc = sourceVolumes.get(0);
StringSet sourceInternalSiteNames = new StringSet();
// both the active and the standby copies
if (RPHelper.isMetroPointVolume(_dbClient, firstSrc)) {
StringSet associatedVolumes = firstSrc.getAssociatedVolumes();
if (associatedVolumes != null && !associatedVolumes.isEmpty()) {
for (String associatedVolumeStr : associatedVolumes) {
URI associatedVolumeURI = URI.create(associatedVolumeStr);
Volume associatedVolume = _dbClient.queryObject(Volume.class, associatedVolumeURI);
sourceInternalSiteNames.add(associatedVolume.getInternalSiteName());
if (NullColumnValueGetter.isNotNullValue(associatedVolume.getRpCopyName())) {
if (associatedVolume.getRpCopyName().equals(copyName)) {
isSource = !isMPStandby;
internalSiteName = associatedVolume.getInternalSiteName();
}
}
}
}
// determine the internal site name for a source copy
} else {
sourceInternalSiteNames.add(firstSrc.getInternalSiteName());
if (NullColumnValueGetter.isNotNullValue(firstSrc.getRpCopyName())) {
if (firstSrc.getRpCopyName().equals(copyName)) {
isSource = true;
internalSiteName = firstSrc.getInternalSiteName();
}
}
}
// determine the internal site name for a target copy
for (String targetURIString : firstSrc.getRpTargets()) {
Volume tgtVolume = _dbClient.queryObject(Volume.class, URI.create(targetURIString));
if (NullColumnValueGetter.isNotNullValue(tgtVolume.getRpCopyName()) && tgtVolume.getRpCopyName().equals(copyName)) {
isTarget = true;
internalSiteName = tgtVolume.getInternalSiteName();
}
}
if (internalSiteName == null) {
throw APIException.badRequests.unableToFindTheSpecifiedCopy(copyName);
}
// if we're adding volumes to a target, we need to know if it's local or remote
String targetType = RPHelper.LOCAL;
int copyType = RecoverPointCGCopyType.PRODUCTION.getCopyNumber();
if (isTarget) {
if (sourceInternalSiteNames.contains(internalSiteName)) {
copyType = RecoverPointCGCopyType.LOCAL.getCopyNumber();
targetType = RPHelper.LOCAL;
} else {
copyType = RecoverPointCGCopyType.REMOTE.getCopyNumber();
targetType = RPHelper.REMOTE;
}
}
capabilities.put(VirtualPoolCapabilityValuesWrapper.RP_COPY_TYPE, copyType);
RPProtectionRecommendation rpProtectionRecommendation = new RPProtectionRecommendation();
rpProtectionRecommendation.setProtectionDevice(protectionSystem.getId());
RPRecommendation journalRecommendation = getBlockScheduler().buildJournalRecommendation(rpProtectionRecommendation, internalSiteName, new Long(capabilities.getSize()).toString(), journalVarray, journalVpool, protectionSystem, capabilities, capabilities.getResourceCount(), null, false);
if (journalRecommendation == null) {
throw APIException.badRequests.unableToFindSuitableJournalRecommendation();
}
String copyTypeString = RPHelper.SOURCE;
if (isSource) {
rpProtectionRecommendation.setSourceJournalRecommendation(journalRecommendation);
}
if (isMPStandby) {
rpProtectionRecommendation.setStandbyJournalRecommendation(journalRecommendation);
copyTypeString = "standby " + RPHelper.SOURCE;
}
if (isTarget) {
List<RPRecommendation> journalRecommendations = Lists.newArrayList();
journalRecommendations.add(journalRecommendation);
rpProtectionRecommendation.setTargetJournalRecommendations(journalRecommendations);
copyTypeString = targetType + " " + RPHelper.TARGET;
}
List<Recommendation> recommendations = Lists.newArrayList();
recommendations.add(rpProtectionRecommendation);
// need to set the journal copy name to something unique
param.setName(copyName + "_" + task);
_log.info("Request to add journal capacity to {} copy {}", copyTypeString, copyName);
_log.info("Copy {} is protected by RP Site {}", copyName, internalSiteName);
TaskList taskList = new TaskList();
Map<VpoolUse, List<Recommendation>> recommendationMap = new HashMap<VpoolUse, List<Recommendation>>();
recommendationMap.put(VpoolUse.ROOT, recommendations);
return this.createVolumes(param, project, journalVarray, journalVpool, recommendationMap, taskList, task, capabilities);
}
use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class RPBlockServiceApiImpl method createRecoverPointVolume.
/**
* Prepare the volume to be used by the controllers for RP.
*
* This includes preparing the volume for any of the leveraged technologies (ex: VPLEX) and
* lastly for RP.
*
* @param rpRec The rec for the RP volume to get most of the info in preparing it
* @param rpVolumeName Volume name
* @param project Project for the volume
* @param capabilities Capabilities for the volume create
* @param consistencyGroup CG for the volume
* @param param Volume create param for this volume
* @param protectionSystemURI URI for the Protection System being used
* @param personalityType Personality of the volume
* @param rsetName Replication set name
* @param preCreatedVolume An optionally pre-created source volume, non-null when calling this method to create a SOURCE volume.
* @param sourceVolume Source volume. Sent down if we're making a target/metadata that needs to be associated to this volume.
* @param taskList Tasklist to capture all tasks for the UI
* @param task Task Id
* @param copyName RP Copy Name
* @param descriptors Descriptors to be populated
* @param changeVpoolVolume Existing volume for change vpool volume if it exist
* @param isChangeVpool Boolean to indicate if this is a change vpool op
* @param isSrcAndHaSwapped Boolean to indicate if this is a swapped Src and HA op
* @param productionCopy whether this is a production copy or not
* @return Prepared RP Volume
*/
private Volume createRecoverPointVolume(RPRecommendation rpRec, String rpVolumeName, Project project, VirtualPoolCapabilityValuesWrapper capabilities, BlockConsistencyGroup consistencyGroup, VolumeCreate param, URI protectionSystemURI, Volume.PersonalityTypes personalityType, String rsetName, Volume preCreatedVolume, Volume sourceVolume, TaskList taskList, String task, String copyName, List<VolumeDescriptor> descriptors, Volume changeVpoolVolume, boolean isChangeVpool, boolean isSrcAndHaSwapped, boolean productionCopy) {
boolean isPreCreatedVolume = (preCreatedVolume != null);
Volume rpVolume = preCreatedVolume;
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, rpRec.getVirtualArray());
VirtualPool vpool = rpRec.getVirtualPool();
String rpInternalSiteName = rpRec.getInternalSiteName();
URI storagePoolUri = rpRec.getSourceStoragePool();
URI storageSystemUri = rpRec.getSourceStorageSystem();
String size = String.valueOf(rpRec.getSize());
// If the copy name was passed in as null, let's get it from the cg or create it
if (copyName == null) {
copyName = retrieveRpCopyName(vpool, varray, consistencyGroup, productionCopy);
}
// Determine if we're creating a RP+VPLEX or MetroPoint volume
boolean vplex = VirtualPool.vPoolSpecifiesHighAvailability(vpool);
_log.info(String.format("Prepare %s Volume %s %s(%s/%s)%s. It will be placed in CG [%s] and " + "will be protected by RecoverPoint (Protection System: %s) with RP Copy Name [%s] on RP Internal Site [%s] " + "as part of RP Replication Set [%s].", personalityType.toString(), (vplex ? "(VPLEX) -" : "-"), rpVolumeName, varray.getLabel(), vpool.getLabel(), (isChangeVpool ? ". This is an existing volume that is involved in a change virtual pool operation." : ""), consistencyGroup.getLabel(), protectionSystemURI.toString(), copyName, rpInternalSiteName, rsetName));
if (vplex) {
List<Recommendation> vplexRecs = new ArrayList<Recommendation>();
// Add VPLEX Source Rec
vplexRecs.add(0, rpRec.getVirtualVolumeRecommendation());
// Add VPLEX HA Rec, if it exists
if (rpRec.getHaRecommendation() != null) {
vplexRecs.add(1, rpRec.getHaRecommendation().getVirtualVolumeRecommendation());
}
// Prepare VPLEX specific volume info
rpVolume = prepareVPlexVolume(vplexRecs, project, varray, vpool, storagePoolUri, storageSystemUri, capabilities, consistencyGroup, param, rpVolumeName, size, descriptors, taskList, task, personalityType, isChangeVpool, changeVpoolVolume);
}
// Prepare RP specific volume info
rpVolume = prepareVolume(rpVolume, project, varray, vpool, size, rpRec, rpVolumeName, consistencyGroup, protectionSystemURI, personalityType, rsetName, rpInternalSiteName, copyName, sourceVolume, vplex, changeVpoolVolume, isPreCreatedVolume);
boolean createTask = isTaskRequired(rpVolume, capabilities, vplex, taskList);
if (createTask) {
// Create a task for this volume
createTaskForVolume(rpVolume, capabilities, taskList, task);
}
return rpVolume;
}
use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class SRDFBlockServiceApiImpl method upgradeToSRDFTargetVolume.
/**
* Upgrade a local block volume to a protected SRDF volume
*
* @param volume
* -- srdf source volume (existing).
* @param vpool
* -- Requested vpool.
* @param taskId
* @throws InternalException
*/
private List<VolumeDescriptor> upgradeToSRDFTargetVolume(final Volume volume, final VirtualPool vpool, final VirtualPoolChangeParam cosChangeParam, final String taskId) throws InternalException {
VirtualPoolCapabilityValuesWrapper capabilities = new VirtualPoolCapabilityValuesWrapper();
capabilities.put(VirtualPoolCapabilityValuesWrapper.BLOCK_CONSISTENCY_GROUP, volume.getConsistencyGroup());
List<Recommendation> recommendations = getRecommendationsForVirtualPoolChangeRequest(volume, vpool, cosChangeParam);
if (recommendations.isEmpty()) {
throw APIException.badRequests.noStorageFoundForVolume();
}
// Call out to the respective block service implementation to prepare and create the
// volumes based on the recommendations.
Project project = _dbClient.queryObject(Project.class, volume.getProject());
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, volume.getVirtualArray());
// Generate a VolumeCreate object that contains the information that createVolumes likes to
// consume.
VolumeCreate param = new VolumeCreate(volume.getLabel(), String.valueOf(volume.getCapacity()), 1, vpool.getId(), volume.getVirtualArray(), volume.getProject().getURI());
capabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, new Integer(1));
if (volume.getIsComposite()) {
// add meta volume properties to the capabilities instance
capabilities.put(VirtualPoolCapabilityValuesWrapper.IS_META_VOLUME, volume.getIsComposite());
capabilities.put(VirtualPoolCapabilityValuesWrapper.META_VOLUME_TYPE, volume.getCompositionType());
capabilities.put(VirtualPoolCapabilityValuesWrapper.META_VOLUME_MEMBER_COUNT, volume.getMetaMemberCount());
capabilities.put(VirtualPoolCapabilityValuesWrapper.META_VOLUME_MEMBER_SIZE, volume.getMetaMemberSize());
_log.debug(String.format("Capabilities : isMeta: %s, Meta Type: %s, Member size: %s, Count: %s", capabilities.getIsMetaVolume(), capabilities.getMetaVolumeType(), capabilities.getMetaVolumeMemberSize(), capabilities.getMetaVolumeMemberCount()));
}
TaskList taskList = new TaskList();
// Prepare the Bourne Volumes to be created and associated
// with the actual storage system volumes created. Also create
// a BlockTaskList containing the list of task resources to be
// returned for the purpose of monitoring the volume creation
// operation for each volume to be created.
String volumeLabel = param.getName();
final BlockConsistencyGroup consistencyGroup = capabilities.getBlockConsistencyGroup() == null ? null : _dbClient.queryObject(BlockConsistencyGroup.class, capabilities.getBlockConsistencyGroup());
// prepare the volumes
List<URI> volumeURIs = prepareRecommendedVolumes(taskId, taskList, project, varray, vpool, capabilities.getResourceCount(), recommendations, consistencyGroup, volumeLabel, param.getSize());
List<VolumeDescriptor> resultListVolumeDescriptors = new ArrayList<>();
// Execute the volume creations requests for each recommendation.
Iterator<Recommendation> recommendationsIter = recommendations.iterator();
while (recommendationsIter.hasNext()) {
Recommendation recommendation = recommendationsIter.next();
try {
List<VolumeDescriptor> volumeDescriptors = createVolumeDescriptors((SRDFRecommendation) recommendation, volumeURIs, capabilities);
// Log volume descriptor information
logVolumeDescriptorPrecreateInfo(volumeDescriptors, taskId);
resultListVolumeDescriptors.addAll(volumeDescriptors);
} catch (InternalException e) {
if (_log.isErrorEnabled()) {
_log.error("Controller error", e);
}
String errorMsg = String.format("Controller error: %s", e.getMessage());
if (volumeURIs != null) {
for (URI volumeURI : volumeURIs) {
Volume volume1 = _dbClient.queryObject(Volume.class, volumeURI);
if (volume1 != null) {
Operation op = new Operation();
ServiceCoded coded = ServiceError.buildServiceError(ServiceCode.API_RP_VOLUME_CREATE_ERROR, errorMsg.toString());
op.setMessage(errorMsg);
op.error(coded);
_dbClient.createTaskOpStatus(Volume.class, volumeURI, taskId, op);
TaskResourceRep volumeTask = toTask(volume1, taskId, op);
if (volume1.getPersonality() != null && volume1.getPersonality().equals(Volume.PersonalityTypes.SOURCE.toString())) {
taskList.getTaskList().add(volumeTask);
}
}
}
}
// the user what succeeded and what failed.
throw APIException.badRequests.cannotCreateSRDFVolumes(e);
}
}
return resultListVolumeDescriptors;
}
use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class SRDFBlockServiceApiImpl method createVolumes.
@Override
public TaskList createVolumes(final VolumeCreate param, final Project project, final VirtualArray varray, final VirtualPool vpool, final Map<VpoolUse, List<Recommendation>> recommendationMap, TaskList taskList, final String task, final VirtualPoolCapabilityValuesWrapper capabilities) throws InternalException {
List<Recommendation> volRecommendations = recommendationMap.get(VpoolUse.ROOT);
Long size = SizeUtil.translateSize(param.getSize());
BlockOrchestrationController controller = getController(BlockOrchestrationController.class, BlockOrchestrationController.BLOCK_ORCHESTRATION_DEVICE);
for (Recommendation volRecommendation : volRecommendations) {
List<VolumeDescriptor> existingDescriptors = new ArrayList<VolumeDescriptor>();
List<VolumeDescriptor> volumeDescriptors = createVolumesAndDescriptors(existingDescriptors, param.getName(), size, project, varray, vpool, volRecommendations, taskList, task, capabilities);
List<URI> volumeURIs = VolumeDescriptor.getVolumeURIs(volumeDescriptors);
try {
controller.createVolumes(volumeDescriptors, task);
} catch (InternalException e) {
if (_log.isErrorEnabled()) {
_log.error("Controller error", e);
}
String errorMsg = String.format("Controller error: %s", e.getMessage());
if (volumeURIs != null) {
for (URI volumeURI : volumeURIs) {
Volume volume = _dbClient.queryObject(Volume.class, volumeURI);
if (volume != null) {
Operation op = new Operation();
ServiceCoded coded = ServiceError.buildServiceError(ServiceCode.API_RP_VOLUME_CREATE_ERROR, errorMsg.toString());
op.setMessage(errorMsg);
op.error(coded);
_dbClient.createTaskOpStatus(Volume.class, volumeURI, task, op);
TaskResourceRep volumeTask = toTask(volume, task, op);
if (volume.getPersonality() != null && volume.getPersonality().equals(Volume.PersonalityTypes.SOURCE.toString())) {
taskList.getTaskList().add(volumeTask);
}
}
}
}
}
}
return taskList;
}
Aggregations