use of com.emc.storageos.blockorchestrationcontroller.BlockOrchestrationController in project coprhd-controller by CoprHD.
the class DefaultBlockFullCopyApiImpl method restoreSource.
/**
* {@inheritDoc}
*/
@Override
public TaskList restoreSource(Volume sourceVolume, Volume fullCopyVolume) {
// Create the task list.
TaskList taskList = new TaskList();
// Create a unique task id.
String taskId = UUID.randomUUID().toString();
// If the source is in a CG, then we will restore the corresponding
// full copies for all the volumes in the CG. Since we did not allow
// full copies for volumes or snaps in CGs prior to Jedi, there should
// be a full copy for all volumes in the CG.
Map<URI, Volume> fullCopyMap = getFullCopySetMap(sourceVolume, fullCopyVolume);
Set<URI> fullCopyURIs = fullCopyMap.keySet();
// Get the id of the source volume.
URI sourceVolumeURI = sourceVolume.getId();
// Get the storage system for the source volume.
StorageSystem sourceSystem = _dbClient.queryObject(StorageSystem.class, sourceVolume.getStorageController());
URI sourceSystemURI = sourceSystem.getId();
// Not really sure why. Change this TBD
for (URI fullCopyURI : fullCopyURIs) {
Operation op = _dbClient.createTaskOpStatus(Volume.class, fullCopyURI, taskId, ResourceOperationTypeEnum.RESTORE_VOLUME_FULL_COPY);
fullCopyMap.get(fullCopyURI).getOpStatus().put(taskId, op);
TaskResourceRep fullCopyVolumeTask = TaskMapper.toTask(fullCopyMap.get(fullCopyURI), taskId, op);
taskList.getTaskList().add(fullCopyVolumeTask);
}
addConsistencyGroupTasks(Arrays.asList(sourceVolume), taskList, taskId, ResourceOperationTypeEnum.RESTORE_CONSISTENCY_GROUP_FULL_COPY);
// Invoke the controller.
try {
BlockOrchestrationController controller = getController(BlockOrchestrationController.class, BlockOrchestrationController.BLOCK_ORCHESTRATION_DEVICE);
controller.restoreFromFullCopy(sourceSystemURI, new ArrayList<URI>(fullCopyURIs), taskId);
} catch (InternalException ie) {
s_logger.error(String.format("Failed to restore source %s from full copy %s", sourceVolumeURI, fullCopyVolume.getId()), ie);
handleFailedRequest(taskId, taskList, new ArrayList<Volume>(fullCopyMap.values()), ie, false);
}
return taskList;
}
use of com.emc.storageos.blockorchestrationcontroller.BlockOrchestrationController in project coprhd-controller by CoprHD.
the class VPlexBlockFullCopyApiImpl method create.
/**
* {@inheritDoc}
*/
@Override
public TaskList create(List<BlockObject> fcSourceObjList, VirtualArray varray, String name, boolean createInactive, int count, String taskId) {
// Populate the descriptors list with all volumes required
// to create the VPLEX volume copies.
int sourceCounter = 0;
URI vplexSrcSystemId = null;
List<Volume> allNewVolumes = new ArrayList<>();
List<Volume> vplexCopyVolumes = new ArrayList<>();
List<VolumeDescriptor> volumeDescriptors = new ArrayList<>();
List<BlockObject> sortedSourceObjectList = sortFullCopySourceList(fcSourceObjList);
Map<URI, VirtualArray> vArrayCache = new HashMap<>();
BlockObject aFCSource = null;
try {
for (BlockObject fcSourceObj : sortedSourceObjectList) {
if (aFCSource == null) {
aFCSource = fcSourceObj;
}
URI fcSourceURI = fcSourceObj.getId();
// volumes in VolumeGroup can be from different vArrays
varray = getVarrayFromCache(vArrayCache, fcSourceObj.getVirtualArray());
String copyName = null;
if (fcSourceObj instanceof Volume && ((Volume) fcSourceObj).getApplication(_dbClient) != null) {
Volume backendVolume = VPlexUtil.getVPLEXBackendVolume((Volume) fcSourceObj, true, _dbClient);
if (NullColumnValueGetter.isNotNullValue(backendVolume.getReplicationGroupInstance())) {
copyName = name + "-" + backendVolume.getReplicationGroupInstance() + (sortedSourceObjectList.size() > 1 ? "-" + ++sourceCounter : "");
}
}
if (copyName == null) {
copyName = name + (sortedSourceObjectList.size() > 1 ? "-" + ++sourceCounter : "");
}
vplexSrcSystemId = fcSourceObj.getStorageController();
if (fcSourceObj instanceof Volume) {
// DO IT ONLY FOR VOLUME CLONE - In case of snapshot new VPLEX volume needs to be created
// Create a volume descriptor for the source VPLEX volume being copied.
// and add it to the descriptors list. Be sure to identify this VPLEX
// volume as the source volume being copied.
VolumeDescriptor vplexSrcVolumeDescr = new VolumeDescriptor(VolumeDescriptor.Type.VPLEX_VIRT_VOLUME, vplexSrcSystemId, fcSourceURI, null, null);
Map<String, Object> descrParams = new HashMap<>();
descrParams.put(VolumeDescriptor.PARAM_IS_COPY_SOURCE_ID, Boolean.TRUE);
vplexSrcVolumeDescr.setParameters(descrParams);
volumeDescriptors.add(vplexSrcVolumeDescr);
} else {
BlockSnapshot sourceSnapshot = (BlockSnapshot) fcSourceObj;
URIQueryResultList queryResults = new URIQueryResultList();
_dbClient.queryByConstraint(AlternateIdConstraint.Factory.getVolumeByAssociatedVolumesConstraint(sourceSnapshot.getParent().getURI().toString()), queryResults);
URI vplexVolumeURI = queryResults.iterator().next();
if (null != vplexVolumeURI) {
Volume vplexVolume = _dbClient.queryObject(Volume.class, vplexVolumeURI);
vplexSrcSystemId = vplexVolume.getStorageController();
}
}
// Get some info about the VPLEX volume being copied and its storage system.
Project vplexSrcProject = BlockFullCopyUtils.queryFullCopySourceProject(fcSourceObj, _dbClient);
StorageSystem vplexSrcSystem = _dbClient.queryObject(StorageSystem.class, vplexSrcSystemId);
Project vplexSystemProject = VPlexBlockServiceApiImpl.getVplexProject(vplexSrcSystem, _dbClient, _tenantsService);
Volume vplexSrcPrimaryVolume = null;
Volume vplexSrcHAVolume = null;
Volume vplexSrcVolume = null;
if (fcSourceObj instanceof Volume) {
// For the VPLEX volume being copied, determine which of the associated
// backend volumes is the primary and, for distributed volumes, which
// is the HA volume. The primary volume will be natively copied and we
// we need to place and prepare a volume to hold the copy. This copy
// will be the primary backend volume for the VPLEX volume copy. For
// a distributed virtual volume, we will need to place and prepare
// a volume to hold the HA volume of the VPLEX volume copy.
vplexSrcVolume = (Volume) fcSourceObj;
StringSet assocVolumeURIs = vplexSrcVolume.getAssociatedVolumes();
if (null == assocVolumeURIs || assocVolumeURIs.isEmpty()) {
s_logger.error("VPLEX volume {} has no backend volumes.", vplexSrcVolume.forDisplay());
throw InternalServerErrorException.internalServerErrors.noAssociatedVolumesForVPLEXVolume(vplexSrcVolume.forDisplay());
}
Iterator<String> assocVolumeURIsIter = assocVolumeURIs.iterator();
while (assocVolumeURIsIter.hasNext()) {
URI assocVolumeURI = URI.create(assocVolumeURIsIter.next());
Volume assocVolume = _dbClient.queryObject(Volume.class, assocVolumeURI);
if (assocVolume.getVirtualArray().toString().equals(varray.getId().toString())) {
vplexSrcPrimaryVolume = assocVolume;
} else {
vplexSrcHAVolume = assocVolume;
}
}
}
// Get the capabilities
VirtualPool vpool = BlockFullCopyUtils.queryFullCopySourceVPool(fcSourceObj, _dbClient);
VirtualPoolCapabilityValuesWrapper capabilities = getCapabilitiesForFullCopyCreate(fcSourceObj, vpool, count);
// Get the number of copies to create and the size of the volumes.
// Note that for the size, we must use the actual provisioned size
// of the source side backend volume. The size passed in the
// capabilities will be the size of the VPLEX volume. When the
// source side backend volume for the copy is provisioned, you
// might not get that actual size. On VMAX, the size will be slightly
// larger while for VNX the size will be exactly what is requested.
// So, if the source side is a VMAX, the source side for the copy
// will be slightly larger than the size in the capabilities. If the HA
// side is VNX and we use the size in the capabilities, then you will
// get exactly that size for the HA backend volume. As a result, source
// side backend volume for the copy will be slightly larger than the
// HA side. Now the way a VPLEX copy is made is it uses native full
// copy to create a native full copy of the source side backend
// volume. It then provisions the HA side volume. The new source side
// backend copy is then imported into VPLEX in the same way as is done
// for a vpool change that imports a volume to VPLEX. This code in the
// VPLEX controller creates a local VPLEX volume using the source side
// copy and for a distributed volume it then attaches as a remote
// mirror the HA backend volume that is provisioned. If the HA volume
// is slightly smaller, then this will fail on the VPLEX. So, we must
// ensure that HA side volume is big enough by using the provisioned
// capacity of the source side backend volume of the VPLEX volume being
// copied.
long size = 0L;
List<Volume> vplexCopyPrimaryVolumes = null;
if (null != vplexSrcPrimaryVolume) {
size = vplexSrcPrimaryVolume.getProvisionedCapacity();
// Place and prepare a volume for each copy to serve as a native
// copy of a VPLEX backend volume. The VPLEX backend volume that
// is copied is the backend volume in the same virtual array as the
// VPLEX volume i.e, the primary backend volume. Create
// descriptors for these prepared volumes and add them to the list.
vplexCopyPrimaryVolumes = prepareFullCopyPrimaryVolumes(copyName, count, vplexSrcPrimaryVolume, capabilities, volumeDescriptors, vpool);
} else {
// Get the provisioned capacity of the snapshot
size = ((BlockSnapshot) fcSourceObj).getProvisionedCapacity();
// Place and prepare a back-end volume for each block snapshot
vplexCopyPrimaryVolumes = prepareFullCopyPrimaryVolumes(copyName, count, fcSourceObj, capabilities, volumeDescriptors, vpool);
}
allNewVolumes.addAll(vplexCopyPrimaryVolumes);
// If the VPLEX volume being copied is distributed, then the VPLEX
// HA volume should be non-null. We use the VPLEX scheduler to place
// and then prepare volumes for the HA volumes of the VPLEX volume
// copies. This should be done in the same manner as is done for the
// import volume routine. This is because to form the VPLEX volume
// copy we import the copy of the primary backend volume.
List<Volume> vplexCopyHAVolumes = new ArrayList<>();
if (vplexSrcHAVolume != null) {
vplexCopyHAVolumes.addAll(prepareFullCopyHAVolumes(copyName, count, size, vplexSrcSystem, vplexSystemProject, varray, vplexSrcHAVolume, taskId, volumeDescriptors));
}
allNewVolumes.addAll(vplexCopyHAVolumes);
// and add them to the volume descriptors list.
for (int i = 0; i < count; i++) {
// Prepare a new VPLEX volume for each copy.
Volume vplexCopyPrimaryVolume = vplexCopyPrimaryVolumes.get(i);
Volume vplexCopyHAVolume = null;
if (!vplexCopyHAVolumes.isEmpty()) {
vplexCopyHAVolume = vplexCopyHAVolumes.get(i);
}
Volume vplexCopyVolume = prepareFullCopyVPlexVolume(copyName, name, count, i, size, fcSourceObj, vplexSrcProject, varray, vpool, vplexSrcSystemId, vplexCopyPrimaryVolume, vplexCopyHAVolume, taskId, volumeDescriptors);
vplexCopyVolumes.add(vplexCopyVolume);
allNewVolumes.addAll(vplexCopyHAVolumes);
}
}
} catch (Exception e) {
handlePlacementFailure(allNewVolumes);
throw e;
}
// get all tasks
TaskList taskList = getTasksForCreateFullCopy(aFCSource, vplexCopyVolumes, taskId);
// Invoke the VPLEX controller to create the copies.
try {
s_logger.info("Getting Orchestration controller {}.", taskId);
BlockOrchestrationController controller = getController(BlockOrchestrationController.class, BlockOrchestrationController.BLOCK_ORCHESTRATION_DEVICE);
controller.createFullCopy(volumeDescriptors, taskId);
s_logger.info("Successfully invoked controller.");
} catch (InternalException e) {
s_logger.error("Controller error", e);
// Update the status for the VPLEX copy volume and CG tasks.
handleFailedRequest(taskId, taskList, new ArrayList<Volume>(), e, false);
// we were trying to copy.
for (VolumeDescriptor descriptor : volumeDescriptors) {
if (descriptor.getParameters().get(VolumeDescriptor.PARAM_IS_COPY_SOURCE_ID) == null) {
Volume volume = _dbClient.queryObject(Volume.class, descriptor.getVolumeURI());
volume.setInactive(true);
_dbClient.updateObject(volume);
}
}
}
return taskList;
}
use of com.emc.storageos.blockorchestrationcontroller.BlockOrchestrationController in project coprhd-controller by CoprHD.
the class VPlexBlockFullCopyApiImpl method restoreSource.
/**
* {@inheritDoc}
*/
@Override
public TaskList restoreSource(Volume sourceVolume, Volume fullCopyVolume) {
// Create the task list.
TaskList taskList = new TaskList();
// Create a unique task id.
String taskId = UUID.randomUUID().toString();
// If the source is in a CG, then we will restore the corresponding
// full copies for all the volumes in the CG. Since we did not allow
// full copies for volumes or snaps in CGs prior to Jedi, there should
// be a full copy for all volumes in the CG.
Map<URI, Volume> fullCopyMap = getFullCopySetMap(sourceVolume, fullCopyVolume);
Set<URI> fullCopyURIs = fullCopyMap.keySet();
// Get the storage system for the source volume.
StorageSystem sourceSystem = _dbClient.queryObject(StorageSystem.class, sourceVolume.getStorageController());
URI sourceSystemURI = sourceSystem.getId();
// Not really sure why.
for (URI fullCopyURI : fullCopyURIs) {
Operation op = _dbClient.createTaskOpStatus(Volume.class, fullCopyURI, taskId, ResourceOperationTypeEnum.RESTORE_VOLUME_FULL_COPY);
fullCopyMap.get(fullCopyURI).getOpStatus().put(taskId, op);
TaskResourceRep fullCopyVolumeTask = TaskMapper.toTask(fullCopyMap.get(fullCopyURI), taskId, op);
taskList.getTaskList().add(fullCopyVolumeTask);
}
addConsistencyGroupTasks(Arrays.asList(sourceVolume), taskList, taskId, ResourceOperationTypeEnum.RESTORE_CONSISTENCY_GROUP_FULL_COPY);
// Invoke the controller.
try {
BlockOrchestrationController controller = getController(BlockOrchestrationController.class, BlockOrchestrationController.BLOCK_ORCHESTRATION_DEVICE);
controller.restoreFromFullCopy(sourceSystemURI, new ArrayList<>(fullCopyURIs), taskId);
} catch (InternalException ie) {
s_logger.error("Controller error: Failed to restore volume full copy {}", fullCopyVolume.getId(), ie);
handleFailedRequest(taskId, taskList, new ArrayList<>(fullCopyMap.values()), ie, false);
}
return taskList;
}
use of com.emc.storageos.blockorchestrationcontroller.BlockOrchestrationController in project coprhd-controller by CoprHD.
the class AbstractBlockServiceApiImpl method restoreSnapshot.
/**
* Restore the passed parent volume from the passed snapshot of that parent volume.
*
* @param snapshot
* The snapshot to restore
* @param parentVolume
* The volume to be restored.
* @param taskId
* The unique task identifier.
*/
@Override
public void restoreSnapshot(BlockSnapshot snapshot, Volume parentVolume, String syncDirection, String taskId) {
BlockOrchestrationController controller = getController(BlockOrchestrationController.class, BlockOrchestrationController.BLOCK_ORCHESTRATION_DEVICE);
controller.restoreVolume(snapshot.getStorageController(), parentVolume.getPool(), parentVolume.getId(), snapshot.getId(), syncDirection, taskId);
}
use of com.emc.storageos.blockorchestrationcontroller.BlockOrchestrationController in project coprhd-controller by CoprHD.
the class AbstractBlockServiceApiImpl method expandVolume.
/**
* {@inheritDoc}
*/
@Override
public void expandVolume(Volume volume, long newSize, String taskId) throws InternalException {
BlockOrchestrationController controller = getController(BlockOrchestrationController.class, BlockOrchestrationController.BLOCK_ORCHESTRATION_DEVICE);
long expandCapacity = newSize - volume.getCapacity();
StorageScheduler.addVolumeExpansionSizeToReservedCapacityMap(_dbClient, volume, expandCapacity);
VolumeDescriptor descriptor = new VolumeDescriptor(VolumeDescriptor.Type.BLOCK_DATA, volume.getStorageController(), volume.getId(), volume.getPool(), null, null, volume.getCapacity());
List<VolumeDescriptor> descriptors = new ArrayList<VolumeDescriptor>(Arrays.asList(descriptor));
for (VolumeDescriptor volDesc : descriptors) {
volDesc.setVolumeSize(newSize);
}
controller.expandVolume(descriptors, taskId);
}
Aggregations