use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.BlockSnapshotRestoreCompleter in project coprhd-controller by CoprHD.
the class BlockDeviceController method restoreVolumeStep.
public boolean restoreVolumeStep(URI storage, URI pool, URI volume, URI snapshot, Boolean updateOpStatus, String opId) throws ControllerException {
TaskCompleter completer = null;
try {
StorageSystem storageDevice = _dbClient.queryObject(StorageSystem.class, storage);
BlockSnapshot snapObj = _dbClient.queryObject(BlockSnapshot.class, snapshot);
completer = new BlockSnapshotRestoreCompleter(snapObj, opId, updateOpStatus);
getDevice(storageDevice.getSystemType()).doRestoreFromSnapshot(storageDevice, volume, snapshot, completer);
} catch (Exception e) {
_log.error(String.format("restoreVolume failed - storage: %s, pool: %s, volume: %s, snapshot: %s", storage.toString(), pool.toString(), volume.toString(), snapshot.toString()));
ServiceError serviceError = DeviceControllerException.errors.jobFailed(e);
completer.error(_dbClient, serviceError);
doFailTask(BlockSnapshot.class, snapshot, opId, serviceError);
WorkflowStepCompleter.stepFailed(opId, serviceError);
return false;
}
return true;
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.BlockSnapshotRestoreCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method restoreVolume.
/**
* {@inheritDoc}
*/
@Override
public void restoreVolume(URI vplexURI, URI snapshotURI, String opId) throws InternalException {
BlockSnapshot snapshot = getDataObject(BlockSnapshot.class, snapshotURI, _dbClient);
try {
// Generate the Workflow.
Workflow workflow = _workflowService.getNewWorkflow(this, RESTORE_VOLUME_WF_NAME, false, opId);
_log.info("Created restore volume workflow with operation id {}", opId);
// Get some info from the snapshot we need to do the native
// restore of the backend volume. Note that if the snapshot
// is associated with a CG, then all backend volumes in the
// CG will be restored using their corresponding snapshots,
// meaning the VPLEX volumes using those backend volumes
// will be restored.
URI parentSystemURI = snapshot.getStorageController();
StorageSystem parentSystem = getDataObject(StorageSystem.class, parentSystemURI, _dbClient);
URI parentVolumeURI = snapshot.getParent().getURI();
Volume parentVolume = getDataObject(Volume.class, parentVolumeURI, _dbClient);
URI parentPoolURI = parentVolume.getPool();
// Get the VPLEX system.
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
// Get the VPLEX volume(s) to be restored.
List<URI> vplexVolumeURIs = new ArrayList<URI>();
URI cgURI = snapshot.getConsistencyGroup();
if (NullColumnValueGetter.isNullURI(cgURI)) {
// If the snapshot is not in a CG, the only VPLEX
// volume to restore is the VPLEX volume using the
// snapshot parent.
URIQueryResultList queryResults = new URIQueryResultList();
_dbClient.queryByConstraint(AlternateIdConstraint.Factory.getVolumeByAssociatedVolumesConstraint(parentVolumeURI.toString()), queryResults);
URI vplexVolumeURI = queryResults.iterator().next();
vplexVolumeURIs.add(vplexVolumeURI);
} else {
// Otherwise, get all snapshots in the snapset, get the
// parent volume for each snapshot, and get the VLPEX
// volume using the snapshot parent.
List<BlockSnapshot> cgSnaps = ControllerUtils.getSnapshotsPartOfReplicationGroup(snapshot, _dbClient);
for (BlockSnapshot cgSnapshot : cgSnaps) {
URIQueryResultList queryResults = new URIQueryResultList();
_dbClient.queryByConstraint(AlternateIdConstraint.Factory.getVolumeByAssociatedVolumesConstraint(cgSnapshot.getParent().getURI().toString()), queryResults);
URI vplexVolumeURI = queryResults.iterator().next();
vplexVolumeURIs.add(vplexVolumeURI);
}
}
// The workflow depends on if the VPLEX volumes are local
// or distributed.
String waitFor = null;
Volume firstVplexVolume = getDataObject(Volume.class, vplexVolumeURIs.get(0), _dbClient);
if (null == firstVplexVolume.getAssociatedVolumes() || firstVplexVolume.getAssociatedVolumes().isEmpty()) {
_log.error("VPLEX volume {} has no backend volumes.", firstVplexVolume.forDisplay());
throw InternalServerErrorException.internalServerErrors.noAssociatedVolumesForVPLEXVolume(firstVplexVolume.forDisplay());
}
boolean isLocal = firstVplexVolume.getAssociatedVolumes().size() == 1;
if (isLocal) {
// VPLEX volume.
for (URI vplexVolumeURI : vplexVolumeURIs) {
waitFor = createWorkflowStepForInvalidateCache(workflow, vplexSystem, vplexVolumeURI, null, null);
}
// Now create a workflow step to natively restore the backend
// volume from the passed snapshot. Note that if the snapshot
// is associated with a CG, then block controller will restore
// all backend volumes in the CG using their corresponding
// snapshots. We execute this after the invalidate cache. We
// could execute these in parallel for a little better efficiency,
// but what if the invalidate cache fails, but the restore succeeds,
// the cache now has invalid data and a cache read hit could return
// invalid data.
createWorkflowStepForRestoreNativeSnapshot(workflow, parentSystem, parentVolumeURI, snapshotURI, parentPoolURI, waitFor, null);
} else {
for (URI vplexVolumeURI : vplexVolumeURIs) {
// For distributed volumes we take snapshots of and restore the
// source backend volume. Before we can do the restore, we need
// to detach the mirror of the distributed volume. So, create a
// workflow step to detach it from the source.
Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
String detachStepId = workflow.createStepId();
Workflow.Method restoreVolumeRollbackMethod = createRestoreResyncRollbackMethod(vplexURI, vplexVolumeURI, vplexVolume.getConsistencyGroup(), detachStepId);
waitFor = createWorkflowStepForDetachMirror(workflow, vplexSystem, vplexVolume, detachStepId, null, restoreVolumeRollbackMethod);
// We now create a step to invalidate the cache for the
// VPLEX volume. Note that if this step fails we need to
// rollback and reattach the mirror.
createWorkflowStepForInvalidateCache(workflow, vplexSystem, vplexVolumeURI, waitFor, rollbackMethodNullMethod());
// Now create a workflow step to reattach the mirror to initiate
// a rebuild of the mirror for the distributed volume. Note that
// these steps will not run until after the native restore, which
// only gets executed once, not for every VPLEX volume.
createWorkflowStepForAttachMirror(workflow, vplexSystem, vplexVolume, detachStepId, RESTORE_VOLUME_STEP, rollbackMethodNullMethod());
}
// Create a workflow step to native restore the backend volume
// from the passed snapshot. This step is executed after the
// cache has been invalidated for each VPLEX volume. Note that
// if the snapshot is associated with a CG, then block controller
// will restore all backend volumes in the CG using their
// corresponding snapshots. We could execute this in parallel
// with the restore for a little better efficiency, but what if
// the invalidate cache fails, but the restore succeeds, the
// cache now has invalid data and a cache read hit could return
// invalid data. If this step fails, then again, we need to
// be sure and rollback and reattach the mirror. There is
// nothing to rollback for the cache invalidate step. It just
// means there will be no read cache hits on the volume for a
// while until the cache is repopulated.
createWorkflowStepForRestoreNativeSnapshot(workflow, parentSystem, parentVolumeURI, snapshotURI, parentPoolURI, INVALIDATE_CACHE_STEP, rollbackMethodNullMethod());
}
// Execute the workflow.
_log.info("Executing workflow plan");
TaskCompleter completer = new BlockSnapshotRestoreCompleter(snapshot, opId);
String successMsg = String.format("Restore VPLEX volume from snapshot %s of backend volume %s " + "completed successfully", snapshotURI, parentVolumeURI);
workflow.executePlan(completer, successMsg);
_log.info("Workflow plan executing");
} catch (Exception e) {
String failMsg = String.format("Restore VPLEX volume from snapshot %s failed", snapshotURI);
_log.error(failMsg, e);
TaskCompleter completer = new BlockSnapshotRestoreCompleter(snapshot, opId);
ServiceError serviceError = VPlexApiException.errors.restoreVolumeFailed(snapshotURI.toString(), e);
failStep(completer, opId, serviceError);
}
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.BlockSnapshotRestoreCompleter in project coprhd-controller by CoprHD.
the class BlockOrchestrationDeviceController method restoreVolume.
/*
* (non-Javadoc)
*
* @see com.emc.storageos.blockorchestrationcontroller.BlockOrchestrationController#restoreVolume(java.net.URI,
* java.net.URI,
* java.net.URI, java.net.URI, java.lang.String)
*/
@Override
public void restoreVolume(URI storage, URI pool, URI volume, URI snapshot, String syncDirection, String taskId) throws ControllerException {
List<URI> volUris = Arrays.asList(volume);
BlockSnapshotRestoreCompleter completer = new BlockSnapshotRestoreCompleter(snapshot, taskId);
try {
// Validate the volume identities before proceeding
validator.volumeURIs(volUris, true, true, ValCk.ID, ValCk.VPLEX);
// Generate the Workflow.
Workflow workflow = _workflowService.getNewWorkflow(this, RESTORE_VOLUME_FROM_SNAPSHOT_WF_NAME, true, taskId);
// the wait for key returned by previous call
String waitFor = null;
// First, call the RP controller to add RP steps for volume restore from snapshot
waitFor = _rpDeviceController.addPreRestoreVolumeSteps(workflow, storage, volume, snapshot, taskId);
// Call the VplexDeviceController to add its steps for restore volume from snapshot
waitFor = _vplexDeviceController.addStepsForRestoreVolume(workflow, waitFor, storage, pool, volume, snapshot, null, syncDirection, taskId, completer);
// Call the BlockDeviceController to add its steps for restore volume from snapshot
waitFor = _blockDeviceController.addStepsForRestoreVolume(workflow, waitFor, storage, pool, volume, snapshot, Boolean.TRUE, syncDirection, taskId, completer);
// Call the RPDeviceController to add its steps for post restore volume from snapshot
waitFor = _rpDeviceController.addStepsForRestoreVolume(workflow, waitFor, storage, pool, volume, snapshot, null, syncDirection, taskId, completer);
// Call the RP controller to add RP post restore steps
waitFor = _rpDeviceController.addPostRestoreVolumeSteps(workflow, waitFor, storage, volume, snapshot, taskId);
// Finish up and execute the plan.
// The Workflow will handle the TaskCompleter
String successMessage = String.format("Restore of volume %s from %s completed successfully", volume, snapshot);
Object[] callbackArgs = new Object[] { new ArrayList<URI>(volUris) };
workflow.executePlan(completer, successMessage, new WorkflowCallback(), callbackArgs, null, null);
} catch (Exception ex) {
s_logger.error("Could not restore volume: " + volUris.toString(), ex);
String opName = ResourceOperationTypeEnum.RESTORE_VOLUME_SNAPSHOT.getName();
ServiceError serviceError = DeviceControllerException.errors.restoreVolumeFromSnapshotFailed(volUris.toString(), snapshot.toString(), opName, ex);
completer.error(s_dbClient, _locker, serviceError);
}
}
use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.BlockSnapshotRestoreCompleter in project coprhd-controller by CoprHD.
the class BlockStorageDeviceTest method testRestoreFromSnapshot.
@Test
public void testRestoreFromSnapshot() {
List<BlockSnapshot> snapshots = getSnapshots(_storageSystem);
BlockSnapshot snapshot = snapshots.get(0);
URI volume = getVolumes(_storageSystem).get(0).getId();
String token = UUID.randomUUID().toString() + UUID.randomUUID().toString();
TaskCompleter taskCompleter = new BlockSnapshotRestoreCompleter(snapshot, token);
_deviceController.doRestoreFromSnapshot(_storageSystem, volume, snapshot.getId(), taskCompleter);
}
Aggregations