use of com.emc.storageos.api.service.impl.placement.VpoolUse in project coprhd-controller by CoprHD.
the class RPBlockServiceApiImpl method upgradeToMetroPointVolume.
/**
* Upgrade a local block volume to a protected RP volume
*
* @param volume the existing volume being protected.
* @param newVpool the requested virtual pool
* @param taskId the task identifier
* @throws InternalException
*/
private void upgradeToMetroPointVolume(Volume volume, VirtualPool newVpool, VirtualPoolChangeParam vpoolChangeParam, String taskId) throws InternalException {
_log.info(String.format("Upgrade [%s] to MetroPoint", volume.getLabel()));
Project project = _dbClient.queryObject(Project.class, volume.getProject());
// Now that we have a handle on the current vpool, let's set the new vpool on the volume.
// The volume will not be persisted just yet but we need to have the new vpool to
// properly make placement decisions and to add reference to the new vpool to the
// recommendation objects that will be created.
URI currentVpool = volume.getVirtualPool();
volume.setVirtualPool(newVpool.getId());
List<Recommendation> recommendations = getRecommendationsForVirtualPoolChangeRequest(volume, newVpool, vpoolChangeParam, null);
volume.setVirtualPool(currentVpool);
if (recommendations.isEmpty()) {
throw APIException.badRequests.noStorageFoundForVolume();
}
// Get the volume's varray
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, newVpool.getId(), volume.getVirtualArray(), volume.getProject().getURI());
VirtualPoolCapabilityValuesWrapper capabilities = new VirtualPoolCapabilityValuesWrapper();
capabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, 1);
capabilities.put(VirtualPoolCapabilityValuesWrapper.BLOCK_CONSISTENCY_GROUP, volume.getConsistencyGroup());
TaskList taskList = new TaskList();
createTaskForVolume(volume, 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.api.service.impl.placement.VpoolUse 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.api.service.impl.placement.VpoolUse in project coprhd-controller by CoprHD.
the class SRDFBlockServiceApiImpl method upgradeToTargetVolume.
/**
* Upgrade a local block volume to a protected SRDF volume
*
* @param volume
* -- VPlex volume (existing).
* @param vpool
* -- Requested vpool.
* @param taskId
* @throws InternalException
*/
private void upgradeToTargetVolume(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()));
}
Map<VpoolUse, List<Recommendation>> recommendationMap = new HashMap<VpoolUse, List<Recommendation>>();
recommendationMap.put(VpoolUse.ROOT, recommendations);
createVolumes(param, project, varray, vpool, recommendationMap, null, taskId, capabilities);
}
use of com.emc.storageos.api.service.impl.placement.VpoolUse 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.api.service.impl.placement.VpoolUse in project coprhd-controller by CoprHD.
the class MigrationService method migrateVolume.
/**
* Performs a non-disruptive migration for the passed VPLEX virtual volume.
* The backend volume of the VPLEX volume that is migrated is the backend
* volume on the passed source storage system. The volume is migrated to the
* passed target storage system, which must be connected to the same VPLEX
* cluster as the source storage system.
*
* @prereq none
*
* @param migrateParam A reference to the migration parameters.
* @deprecated Use the Change Virtual Pool API instead
* @brief Perform a non-disruptive migration for a VPLEX volume.
* @return A TaskResourceRep for the volume being migrated.
* @throws InternalException
*/
@Deprecated
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_ADMIN })
public TaskResourceRep migrateVolume(MigrationParam migrateParam) throws InternalException {
// Create a unique task id.
String taskId = UUID.randomUUID().toString();
s_logger.info("Migrate volume {} from storage system {} to storage system {}", new Object[] { migrateParam.getVolume(), migrateParam.getSrcStorageSystem(), migrateParam.getTgtStorageSystem() });
// Verify the requested volume supports migration.
Volume vplexVolume = verifyRequestedVolumeSupportsMigration(migrateParam.getVolume());
s_logger.debug("Verfified requested volume");
// Make sure that we don't have some pending
// operation against the volume
checkForPendingTasks(Arrays.asList(vplexVolume.getTenant().getURI()), Arrays.asList(vplexVolume));
// Determine the backend volume of the requested VPlex volume that
// is to be migrated. It is the volume on the passed source storage
// system.
Volume migrationSrc = getMigrationSource(vplexVolume, migrateParam.getSrcStorageSystem());
s_logger.debug("Migration source is {}", migrationSrc.getId());
// The project for the migration target will be the same as that
// of the source.
Project migrationTgtProject = _permissionsHelper.getObjectById(migrationSrc.getProject().getURI(), Project.class);
s_logger.debug("Migration target project is {}", migrationTgtProject.getId());
// The VirtualArray for the migration target will be the same as
// that of the source.
VirtualArray migrationTargetVarray = _permissionsHelper.getObjectById(migrationSrc.getVirtualArray(), VirtualArray.class);
s_logger.debug("Migration target VirtualArray is {}", migrationTargetVarray.getId());
// Verify the requested target storage system exists and
// is a system to which the migration source volume can
// be migrated.
verifyTargetStorageSystemForMigration(migrateParam.getVolume(), vplexVolume.getStorageController(), migrateParam.getSrcStorageSystem(), migrateParam.getTgtStorageSystem());
s_logger.debug("Verified target storage system {}", migrateParam.getTgtStorageSystem());
// Get the VirtualPool for the migration target.
VirtualPool migrationTgtCos = getVirtualPoolForMigrationTarget(migrateParam.getVirtualPool(), vplexVolume, migrationSrc);
s_logger.debug("Migration target VirtualPool is {}", migrationTgtCos.getId());
// Get the VPlex storage system for the virtual volume.
URI vplexSystemURI = vplexVolume.getStorageController();
Set<URI> requestedVPlexSystems = new HashSet<URI>();
requestedVPlexSystems.add(vplexSystemURI);
// Get a placement recommendation on the requested target storage
// system connected to the VPlex storage system of the VPlex volume.
VPlexScheduler vplexScheduler = _vplexBlockServiceApi.getBlockScheduler();
VirtualPoolCapabilityValuesWrapper cosWrapper = new VirtualPoolCapabilityValuesWrapper();
cosWrapper.put(VirtualPoolCapabilityValuesWrapper.SIZE, migrationSrc.getCapacity());
cosWrapper.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, new Integer(1));
List<Recommendation> recommendations = vplexScheduler.scheduleStorage(migrationTargetVarray, requestedVPlexSystems, migrateParam.getTgtStorageSystem(), migrationTgtCos, false, null, null, cosWrapper, migrationTgtProject, VpoolUse.ROOT, new HashMap<VpoolUse, List<Recommendation>>());
if (recommendations.isEmpty()) {
throw APIException.badRequests.noStorageFoundForVolumeMigration(migrationTgtCos.getLabel(), migrationTargetVarray.getLabel(), vplexVolume.getId());
}
s_logger.debug("Got recommendation for migration target");
// There should be a single recommendation.
Recommendation recommendation = recommendations.get(0);
URI recommendedSystem = recommendation.getSourceStorageSystem();
URI recommendedPool = recommendation.getSourceStoragePool();
s_logger.debug("Recommendation storage system is {}", recommendedSystem);
s_logger.debug("Recommendation storage pool is {}", recommendedPool);
// Prepare the migration target.
List<URI> migrationTgts = new ArrayList<URI>();
Map<URI, URI> poolTgtMap = new HashMap<URI, URI>();
Long size = _vplexBlockServiceApi.getVolumeCapacity(migrationSrc);
Volume migrationTgt = VPlexBlockServiceApiImpl.prepareVolumeForRequest(size, migrationTgtProject, migrationTargetVarray, migrationTgtCos, recommendedSystem, recommendedPool, migrationSrc.getLabel(), ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME, taskId, _dbClient);
URI migrationTgtURI = migrationTgt.getId();
migrationTgts.add(migrationTgtURI);
poolTgtMap.put(recommendedPool, migrationTgtURI);
s_logger.debug("Prepared migration target volume {}", migrationTgtURI);
// Prepare the migration.
Map<URI, URI> migrationsMap = new HashMap<URI, URI>();
Migration migration = _vplexBlockServiceApi.prepareMigration(migrateParam.getVolume(), migrationSrc.getId(), migrationTgt.getId(), taskId);
migrationsMap.put(migrationTgtURI, migration.getId());
s_logger.debug("Prepared migration {}", migration.getId());
// Create a task for the virtual volume being migrated and set the
// initial task state to pending.
Operation op = _dbClient.createTaskOpStatus(Volume.class, vplexVolume.getId(), taskId, ResourceOperationTypeEnum.MIGRATE_BLOCK_VOLUME);
TaskResourceRep task = toTask(vplexVolume, taskId, op);
s_logger.debug("Created task for volume {}", migrateParam.getVolume());
try {
VPlexController controller = _vplexBlockServiceApi.getController();
String successMsg = String.format("Migration succeeded for volume %s", migrateParam.getVolume());
String failMsg = String.format("Migration failed for volume %s", migrateParam.getVolume());
controller.migrateVolumes(vplexSystemURI, migrateParam.getVolume(), migrationTgts, migrationsMap, poolTgtMap, (migrateParam.getVirtualPool() != null ? migrateParam.getVirtualPool() : null), null, successMsg, failMsg, null, taskId, null);
s_logger.debug("Got VPlex controller and created migration workflow");
} catch (InternalException e) {
s_logger.error("Controller Error", e);
String errMsg = String.format("Controller Error: %s", e.getMessage());
task.setState(Operation.Status.error.name());
task.setMessage(errMsg);
Operation opStatus = new Operation(Operation.Status.error.name(), errMsg);
_dbClient.updateTaskOpStatus(Volume.class, task.getResource().getId(), taskId, opStatus);
migrationTgt.setInactive(true);
_dbClient.persistObject(migrationTgt);
migration.setInactive(true);
_dbClient.persistObject(migration);
throw e;
}
return task;
}
Aggregations