use of com.emc.storageos.api.service.impl.placement.VPlexScheduler 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;
}
use of com.emc.storageos.api.service.impl.placement.VPlexScheduler in project coprhd-controller by CoprHD.
the class VPlexBlockFullCopyApiImpl method prepareFullCopyHAVolumes.
/**
* Places and prepares the HA volumes when copying a distributed VPLEX
* volume.
*
* @param name The base name for the volume.
* @param copyCount The number of copies to be made.
* @param size The size for the HA volume.
* @param vplexSystem A reference to the VPLEX storage system.
* @param vplexSystemProject A reference to the VPLEX system project.
* @param srcVarray The virtual array for the VPLEX volume being copied.
* @param srcHAVolume The HA volume of the VPLEX volume being copied.
* @param taskId The task identifier.
* @param volumeDescriptors The list of descriptors.
*
* @return A list of the prepared HA volumes for the VPLEX volume copy.
*/
private List<Volume> prepareFullCopyHAVolumes(String name, int copyCount, Long size, StorageSystem vplexSystem, Project vplexSystemProject, VirtualArray srcVarray, Volume srcHAVolume, String taskId, List<VolumeDescriptor> volumeDescriptors) {
List<Volume> copyHAVolumes = new ArrayList<>();
// Get the storage placement recommendations for the volumes.
// Placement must occur on the same VPLEX system
Set<URI> vplexSystemURIS = new HashSet<>();
vplexSystemURIS.add(vplexSystem.getId());
VirtualArray haVarray = _dbClient.queryObject(VirtualArray.class, srcHAVolume.getVirtualArray());
VirtualPool haVpool = _dbClient.queryObject(VirtualPool.class, srcHAVolume.getVirtualPool());
VirtualPoolCapabilityValuesWrapper haCapabilities = new VirtualPoolCapabilityValuesWrapper();
haCapabilities.put(VirtualPoolCapabilityValuesWrapper.SIZE, size);
haCapabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, copyCount);
VirtualPool vpool = BlockFullCopyUtils.queryFullCopySourceVPool(srcHAVolume, _dbClient);
if (VirtualPool.ProvisioningType.Thin.toString().equalsIgnoreCase(vpool.getSupportedProvisioningType())) {
haCapabilities.put(VirtualPoolCapabilityValuesWrapper.THIN_PROVISIONING, Boolean.TRUE);
// To guarantee that storage pool for a copy has enough physical
// space to contain current allocated capacity of thin source volume
haCapabilities.put(VirtualPoolCapabilityValuesWrapper.THIN_VOLUME_PRE_ALLOCATE_SIZE, BlockFullCopyUtils.getAllocatedCapacityForFullCopySource(srcHAVolume, _dbClient));
}
List<Recommendation> recommendations = ((VPlexScheduler) _scheduler).scheduleStorageForImport(srcVarray, vplexSystemURIS, haVarray, haVpool, haCapabilities);
if (recommendations.isEmpty()) {
throw APIException.badRequests.noStorageForHaVolumesForVplexVolumeCopies();
}
// Prepare the HA volumes for the VPLEX volume copy.
int copyIndex = 1;
for (Recommendation recommendation : recommendations) {
VPlexRecommendation haRecommendation = (VPlexRecommendation) recommendation;
for (int i = 0; i < haRecommendation.getResourceCount(); i++) {
// Determine the name for the HA volume copy.
StringBuilder nameBuilder = new StringBuilder(name);
nameBuilder.append("-1");
if (copyCount > 1) {
nameBuilder.append("-");
nameBuilder.append(copyIndex++);
}
// Prepare the volume.
Volume volume = VPlexBlockServiceApiImpl.prepareVolumeForRequest(size, vplexSystemProject, haVarray, haVpool, haRecommendation.getSourceStorageSystem(), haRecommendation.getSourceStoragePool(), nameBuilder.toString(), null, taskId, _dbClient);
volume.addInternalFlags(Flag.INTERNAL_OBJECT);
_dbClient.persistObject(volume);
copyHAVolumes.add(volume);
// Create the volume descriptor and add it to the passed list.
VolumeDescriptor volumeDescriptor = new VolumeDescriptor(VolumeDescriptor.Type.BLOCK_DATA, volume.getStorageController(), volume.getId(), volume.getPool(), haCapabilities);
volumeDescriptors.add(volumeDescriptor);
}
}
return copyHAVolumes;
}
Aggregations