use of com.emc.storageos.svcs.errorhandling.model.ServiceCoded in project coprhd-controller by CoprHD.
the class BlockSnapshotSessionManager method linkTargetVolumesToSnapshotSession.
/**
* Implements a request to create and link new target volumes to the
* BlockSnapshotSession instance with the passed URI.
*
* @param snapSessionURI The URI of a BlockSnapshotSession instance.
* @param param The linked target information.
*
* @return A TaskResourceRep.
*/
public TaskList linkTargetVolumesToSnapshotSession(URI snapSessionURI, SnapshotSessionLinkTargetsParam param) {
s_logger.info("START link new targets for snapshot session {}", snapSessionURI);
// Get the snapshot session.
BlockSnapshotSession snapSession = BlockSnapshotSessionUtils.querySnapshotSession(snapSessionURI, _uriInfo, _dbClient, true);
BlockObject snapSessionSourceObj = null;
List<BlockObject> snapSessionSourceObjs = getAllSnapshotSessionSources(snapSession);
snapSessionSourceObj = snapSessionSourceObjs.get(0);
// Get the project for the snapshot session source object.
Project project = BlockSnapshotSessionUtils.querySnapshotSessionSourceProject(snapSessionSourceObj, _dbClient);
BlockSnapshotSessionApi snapSessionApiImpl = determinePlatformSpecificImplForSource(snapSessionSourceObj);
boolean inApplication = false;
if (snapSessionSourceObj instanceof Volume && ((Volume) snapSessionSourceObj).getApplication(_dbClient) != null) {
inApplication = true;
} else if (snapSessionSourceObj instanceof BlockSnapshot) {
BlockSnapshot sourceSnap = (BlockSnapshot) snapSessionSourceObj;
NamedURI namedUri = sourceSnap.getParent();
if (!NullColumnValueGetter.isNullNamedURI(namedUri)) {
Volume source = _dbClient.queryObject(Volume.class, namedUri.getURI());
if (source != null && source.getApplication(_dbClient) != null) {
inApplication = true;
}
}
}
// Get the target information.
int newLinkedTargetsCount = param.getNewLinkedTargets().getCount();
String newTargetsName = param.getNewLinkedTargets().getTargetName();
String newTargetsCopyMode = param.getNewLinkedTargets().getCopyMode();
if (newTargetsCopyMode == null) {
newTargetsCopyMode = BlockSnapshot.CopyMode.nocopy.name();
}
// Validate that the requested new targets can be linked to the snapshot session.
snapSessionApiImpl.validateLinkNewTargetsRequest(snapSessionSourceObj, project, newLinkedTargetsCount, newTargetsName, newTargetsCopyMode);
// Prepare the BlockSnapshot instances to represent the new linked targets.
List<Map<URI, BlockSnapshot>> snapshots = snapSessionApiImpl.prepareSnapshotsForSession(snapSessionSourceObjs, 0, newLinkedTargetsCount, newTargetsName, inApplication);
// Create a unique task identifier.
String taskId = UUID.randomUUID().toString();
TaskList response = new TaskList();
List<DataObject> preparedObjects = new ArrayList<>();
// Create a task for the snapshot session.
Operation op = new Operation();
op.setResourceType(ResourceOperationTypeEnum.LINK_SNAPSHOT_SESSION_TARGETS);
_dbClient.createTaskOpStatus(BlockSnapshotSession.class, snapSessionURI, taskId, op);
snapSession.getOpStatus().put(taskId, op);
response.getTaskList().add(toTask(snapSession, taskId));
List<List<URI>> snapSessionSnapshotURIs = new ArrayList<>();
for (Map<URI, BlockSnapshot> snapshotMap : snapshots) {
// Set Copy Mode
for (Entry<URI, BlockSnapshot> entry : snapshotMap.entrySet()) {
entry.getValue().setCopyMode(newTargetsCopyMode);
}
preparedObjects.addAll(snapshotMap.values());
Set<URI> uris = snapshotMap.keySet();
snapSessionSnapshotURIs.add(Lists.newArrayList(uris));
}
// persist copyMode changes
_dbClient.updateObject(preparedObjects);
// Create and link new targets to the snapshot session.
try {
snapSessionApiImpl.linkNewTargetVolumesToSnapshotSession(snapSessionSourceObj, snapSession, snapSessionSnapshotURIs, newTargetsCopyMode, taskId);
} catch (Exception e) {
String errorMsg = format("Failed to link new targets for snapshot session %s: %s", snapSessionURI, e.getMessage());
ServiceCoded sc = null;
if (e instanceof ServiceCoded) {
sc = (ServiceCoded) e;
} else {
sc = APIException.internalServerErrors.genericApisvcError(errorMsg, e);
}
cleanupFailure(response.getTaskList(), preparedObjects, errorMsg, taskId, sc);
throw e;
}
// Create the audit log entry.
auditOp(OperationTypeEnum.LINK_SNAPSHOT_SESSION_TARGET, true, AuditLogManager.AUDITOP_BEGIN, snapSessionURI.toString(), snapSessionSourceObj.getId().toString(), snapSessionSourceObj.getStorageController().toString());
s_logger.info("FINISH link new targets for snapshot session {}", snapSessionURI);
return response;
}
use of com.emc.storageos.svcs.errorhandling.model.ServiceCoded in project coprhd-controller by CoprHD.
the class BlockDeviceController method relinkTargetsToSnapshotSession.
/**
* {@inheritDoc}
*/
@Override
public void relinkTargetsToSnapshotSession(URI systemURI, URI tgtSnapSessionURI, List<URI> snapshotURIs, Boolean updateStatus, String opId) throws InternalException {
TaskCompleter completer = new BlockSnapshotSessionRelinkTargetsWorkflowCompleter(tgtSnapSessionURI, updateStatus, opId);
try {
// Get a new workflow to execute the linking of the target volumes
// to the new session.
Workflow workflow = _workflowService.getNewWorkflow(this, RELINK_SNAPSHOT_SESSION_TARGETS_WF_NAME, false, opId);
_log.info("Created new workflow to re-link targets to snapshot session {} with operation id {}", tgtSnapSessionURI, opId);
Iterable<URI> snapshotsIterable = snapshotURIs;
BlockSnapshotSession tgtSnapSession = _dbClient.queryObject(BlockSnapshotSession.class, tgtSnapSessionURI);
// For CG's, ensure 1 target per ReplicationGroup
if (tgtSnapSession.hasConsistencyGroup() && NullColumnValueGetter.isNotNullValue(tgtSnapSession.getReplicationGroupInstance())) {
snapshotsIterable = ControllerUtils.ensureOneSnapshotPerReplicationGroup(snapshotURIs, _dbClient);
}
String waitFor = null;
for (URI snapshotURI : snapshotsIterable) {
waitFor = workflow.createStep(RELINK_SNAPSHOT_SESSION_TARGET_STEP_GROUP, String.format("Re-linking target to snapshot session %s", tgtSnapSessionURI), waitFor, systemURI, getDeviceType(systemURI), getClass(), relinkBlockSnapshotSessionTargetMethod(systemURI, tgtSnapSessionURI, snapshotURI), null, null);
}
workflow.executePlan(completer, "Re-link target volumes to block snapshot session successful");
} catch (Exception e) {
_log.error("Re-link target volumes to block snapshot session failed", e);
ServiceCoded serviceException = DeviceControllerException.exceptions.relinkBlockSnapshotSessionTargetsFailed(e);
completer.error(_dbClient, serviceException);
}
}
use of com.emc.storageos.svcs.errorhandling.model.ServiceCoded in project coprhd-controller by CoprHD.
the class BlockDeviceController method restoreSnapshotSession.
/**
* {@inheritDoc}
*/
@Override
public void restoreSnapshotSession(URI systemURI, URI snapSessionURI, Boolean updateStatus, String opId) {
BlockSnapshotSession snapshotSession = _dbClient.queryObject(BlockSnapshotSession.class, snapSessionURI);
TaskCompleter completer = new BlockSnapshotSessionRestoreWorkflowCompleter(snapshotSession.getId(), updateStatus, opId);
try {
// Get a new workflow to restore the snapshot session.
Workflow workflow = _workflowService.getNewWorkflow(this, RESTORE_SNAPSHOT_SESSION_WF_NAME, false, opId);
_log.info("Created new workflow to restore snapshot session {} with operation id {}", snapSessionURI, opId);
String waitFor = null;
// Check if we are dealing with a single volume or a group...
BlockObject sourceObj = null;
if (snapshotSession.hasConsistencyGroup() && NullColumnValueGetter.isNotNullValue(snapshotSession.getReplicationGroupInstance())) {
// We need a single source volume for the session.
BlockConsistencyGroup cg = _dbClient.queryObject(BlockConsistencyGroup.class, snapshotSession.getConsistencyGroup());
List<Volume> nativeVolumes = BlockConsistencyGroupUtils.getActiveNativeVolumesInCG(cg, _dbClient);
// get source group name from the session.
String sourceGroupName = snapshotSession.getReplicationGroupInstance();
for (Volume volume : nativeVolumes) {
if (sourceGroupName.equals(volume.getReplicationGroupInstance())) {
sourceObj = volume;
// get source volume which matches session's RG name
break;
}
}
} else {
sourceObj = BlockObject.fetch(_dbClient, snapshotSession.getParent().getURI());
}
if (sourceObj instanceof Volume && isNonSplitSRDFTargetVolume((Volume) sourceObj)) {
// PRIOR to Restoring R2 Device from its session, we need to
// a) SUSPEND the R1-R2 pair if the Copy Mode is ACTIVE Or
// b) SPLIT the R1-R2 pair if the Copy Mode is SYNC/ ASYNC
Volume sourceVolume = (Volume) sourceObj;
URI srdfSourceVolumeURI = sourceVolume.getSrdfParent().getURI();
Volume srdfSourceVolume = _dbClient.queryObject(Volume.class, srdfSourceVolumeURI);
URI srdfSourceStorageSystemURI = srdfSourceVolume.getStorageController();
if (Mode.ACTIVE.equals(Mode.valueOf(sourceVolume.getSrdfCopyMode()))) {
waitFor = suspendSRDFLinkWorkflowStep(waitFor, srdfSourceStorageSystemURI, srdfSourceVolumeURI, sourceObj.getId(), workflow);
} else {
// split all members the group
Workflow.Method splitMethod = srdfDeviceController.splitSRDFGroupLinkMethod(srdfSourceStorageSystemURI, srdfSourceVolumeURI, sourceObj.getId(), false);
Workflow.Method splitRollbackMethod = srdfDeviceController.resumeGroupPairsMethod(srdfSourceStorageSystemURI, srdfSourceVolumeURI, sourceObj.getId());
waitFor = workflow.createStep(SRDFDeviceController.SPLIT_SRDF_MIRRORS_STEP_GROUP, SRDFDeviceController.SPLIT_SRDF_MIRRORS_STEP_DESC, waitFor, srdfSourceStorageSystemURI, getDeviceType(srdfSourceStorageSystemURI), SRDFDeviceController.class, splitMethod, splitRollbackMethod, null);
}
} else if (sourceObj instanceof Volume && isNonSplitSRDFSourceVolume((Volume) sourceObj)) {
// PRIOR to Restoring R1 Device from its session, we need to SUSPEND the R1-R2 pair if the Copy Mode is
// ACTIVE
Volume srdfSourceVolume = (Volume) sourceObj;
URI srdfSourceStorageSystemURI = srdfSourceVolume.getStorageController();
StringSet targets = srdfSourceVolume.getSrdfTargets();
if (null != targets) {
for (String target : targets) {
if (NullColumnValueGetter.isNotNullValue(target)) {
Volume srdfTargetVolume = _dbClient.queryObject(Volume.class, URI.create(target));
if (null != srdfTargetVolume && Mode.ACTIVE.equals(Mode.valueOf(srdfTargetVolume.getSrdfCopyMode()))) {
waitFor = suspendSRDFLinkWorkflowStep(waitFor, srdfSourceStorageSystemURI, srdfSourceVolume.getId(), srdfTargetVolume.getId(), workflow);
}
break;
}
}
}
}
// Create the workflow step to restore the snapshot session.
waitFor = workflow.createStep(RESTORE_SNAPSHOT_SESSION_STEP_GROUP, String.format("Restore snapshot session %s", snapSessionURI), waitFor, systemURI, getDeviceType(systemURI), getClass(), restoreBlockSnapshotSessionMethod(systemURI, snapSessionURI), rollbackMethodNullMethod(), null);
// Execute the workflow.
workflow.executePlan(completer, "Restore block snapshot session successful");
} catch (Exception e) {
_log.error("Restore block snapshot session failed", e);
ServiceCoded serviceException = DeviceControllerException.exceptions.restoreBlockSnapshotSessionFailed(e);
completer.error(_dbClient, serviceException);
}
}
use of com.emc.storageos.svcs.errorhandling.model.ServiceCoded in project coprhd-controller by CoprHD.
the class HDSMetaVolumeOperations method waitForAsyncHDSJob.
/**
* Waits the thread to till the operation completes.
*
* @param storageDeviceURI
* @param messageId
* @param job
* @param hdsApiFactory
* @return
* @throws HDSException
*/
private JobStatus waitForAsyncHDSJob(URI storageDeviceURI, String messageId, HDSJob job, HDSApiFactory hdsApiFactory) throws HDSException {
JobStatus status = JobStatus.IN_PROGRESS;
if (job == null) {
TaskCompleter taskCompleter = new TaskCompleter() {
@Override
public void ready(DbClient dbClient) throws DeviceControllerException {
}
@Override
public void error(DbClient dbClient, ServiceCoded serviceCoded) throws DeviceControllerException {
}
@Override
protected void complete(DbClient dbClient, Operation.Status status, ServiceCoded coded) throws DeviceControllerException {
}
};
job = new HDSJob(messageId, storageDeviceURI, taskCompleter, "");
} else {
job.setHDSJob(messageId);
}
JobContext jobContext = new JobContext(dbClient, null, null, hdsApiFactory, null, null, null, null);
long startTime = System.currentTimeMillis();
while (true) {
JobPollResult result = job.poll(jobContext, SYNC_WRAPPER_WAIT);
if (result.getJobStatus().equals(JobStatus.IN_PROGRESS) || result.getJobStatus().equals(JobStatus.ERROR)) {
if (System.currentTimeMillis() - startTime > SYNC_WRAPPER_TIME_OUT) {
HDSException.exceptions.asyncTaskFailedTimeout(System.currentTimeMillis() - startTime);
} else {
try {
Thread.sleep(SYNC_WRAPPER_WAIT);
} catch (InterruptedException e) {
log.error("Thread waiting for hds job to complete was interrupted and " + "will be resumed");
}
}
} else {
status = result.getJobStatus();
if (!status.equals(JobStatus.SUCCESS)) {
HDSException.exceptions.asyncTaskFailedWithErrorResponseWithoutErrorCode(messageId, result.getErrorDescription());
}
break;
}
}
return status;
}
use of com.emc.storageos.svcs.errorhandling.model.ServiceCoded in project coprhd-controller by CoprHD.
the class CephCloneOperations method detachSingleClone.
@Override
public void detachSingleClone(StorageSystem storageSystem, URI cloneVolume, TaskCompleter taskCompleter) {
_log.info("START detachSingleClone operation");
try (CephClient cephClient = getClient(storageSystem)) {
Volume cloneObject = _dbClient.queryObject(Volume.class, cloneVolume);
String cloneId = cloneObject.getNativeId();
StoragePool pool = _dbClient.queryObject(StoragePool.class, cloneObject.getPool());
String poolId = pool.getPoolName();
BlockSnapshot sourceSnapshot = _dbClient.queryObject(BlockSnapshot.class, cloneObject.getAssociatedSourceVolume());
String snapshotId = sourceSnapshot.getNativeId();
Volume parentVolume = _dbClient.queryObject(Volume.class, sourceSnapshot.getParent());
String parentVolumeId = parentVolume.getNativeId();
try {
// Flatten image (detach Ceph volume from Ceph snapshot)
// http://docs.ceph.com/docs/master/rbd/rbd-snapshot/#getting-started-with-layering
cephClient.flattenImage(poolId, cloneId);
// Detach links
ReplicationUtils.removeDetachedFullCopyFromSourceFullCopiesList(cloneObject, _dbClient);
cloneObject.setAssociatedSourceVolume(NullColumnValueGetter.getNullURI());
cloneObject.setReplicaState(ReplicationState.DETACHED.name());
_dbClient.updateObject(cloneObject);
// Un-protect snapshot if it was the last child and delete internal interim snapshot
List<String> children = cephClient.getChildren(poolId, parentVolumeId, snapshotId);
if (children.isEmpty()) {
// Unprotect snapshot to enable deleting
if (cephClient.snapIsProtected(poolId, parentVolumeId, snapshotId)) {
cephClient.unprotectSnap(poolId, parentVolumeId, snapshotId);
}
// and should be deleted at the step of detaching during full copy creation workflow
if (sourceSnapshot.checkInternalFlags(Flag.INTERNAL_OBJECT)) {
cephClient.deleteSnap(poolId, parentVolumeId, snapshotId);
// Set to null to prevent handling in cleanUpCloneObjects
snapshotId = null;
_dbClient.markForDeletion(sourceSnapshot);
}
} else if (sourceSnapshot.checkInternalFlags(Flag.INTERNAL_OBJECT)) {
// If the snapshot (not interim) still has children, it may be used for another cloning right now
// So that log the warning for interim snapshot only
_log.warn("Could not delete interim snapshot {} because its Ceph snapshot {}@{} unexpectedly had another child", sourceSnapshot.getId(), parentVolumeId, snapshotId);
}
taskCompleter.ready(_dbClient);
} catch (Exception e) {
// Although detachSingleClone may be again called on error, it is better to remove objects now.
cleanUpCloneObjects(cephClient, poolId, cloneId, snapshotId, parentVolumeId, sourceSnapshot);
throw e;
}
} catch (Exception e) {
BlockObject obj = BlockObject.fetch(_dbClient, cloneVolume);
if (obj != null) {
obj.setInactive(true);
_dbClient.updateObject(obj);
}
_log.error("Encountered an exception", e);
ServiceCoded code = DeviceControllerErrors.ceph.operationFailed("detachSingleClone", e.getMessage());
taskCompleter.error(_dbClient, code);
}
}
Aggregations