/*
* Copyright (c) 2012 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.block.taskcompleter;
import java.net.URI;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.model.BlockObject;
import com.emc.storageos.db.client.model.BlockSnapshot;
import com.emc.storageos.db.client.model.BlockSnapshotSession;
import com.emc.storageos.db.client.model.Operation;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.exceptions.DeviceControllerException;
import com.emc.storageos.services.OperationTypeEnum;
import com.emc.storageos.svcs.errorhandling.model.ServiceCoded;
/**
* Task completer invoked when a workflow creating new BlockSnapshotSession
* instances completes.
*/
@SuppressWarnings("serial")
public class BlockSnapshotSessionCreateWorkflowCompleter extends BlockSnapshotSessionCompleter {
// Message constants.
public static final String SNAPSHOT_SESSION_CREATE_SUCCESS_MSG = "Block Snapshot Session %s created for source %s";
public static final String SNAPSHOT_SESSION_CREATE_FAIL_MSG = "Failed to create Block Snapshot Session %s for source %s";
// A map of the BlockSnapshot instances linked to the session for the request.
private final List<List<URI>> _sessionSnapshotURIs;
// A logger.
private static final Logger s_logger = LoggerFactory.getLogger(BlockSnapshotSessionCreateWorkflowCompleter.class);
/**
* Constructor
*
* @param snapSessionURI The URI of the BlockSnapshotSession instance created in the request.
* @param sessionSnapshotURIs A map of the BlockSnapshot URIs linked to the session for the request.
* @param taskId The unique task identifier.
*/
public BlockSnapshotSessionCreateWorkflowCompleter(URI snapSessionURI, List<List<URI>> sessionSnapshotURIs, String taskId) {
super(snapSessionURI, taskId);
_sessionSnapshotURIs = sessionSnapshotURIs;
}
/**
* {@inheritDoc}
*/
@Override
protected void complete(DbClient dbClient, Operation.Status status, ServiceCoded coded) throws DeviceControllerException {
try {
BlockSnapshotSession snapSession = dbClient.queryObject(BlockSnapshotSession.class, getId());
List<BlockObject> allSources = getAllSources(snapSession, dbClient);
// Record the results.
recordBlockSnapshotSessionOperation(dbClient, OperationTypeEnum.CREATE_SNAPSHOT_SESSION,
status, snapSession, allSources.get(0));
// Update the status map of the snapshot session.
switch (status) {
case error:
// For those BlockSnapshot instances representing linked targets that
// were not successfully created and linked to the array snapshot
// represented by the BlockSnapshotSession instance, mark them inactive.
for (List<URI> snapshotURIs : _sessionSnapshotURIs) {
for (URI snapshotURI : snapshotURIs) {
// Successfully linked targets will be in the list of linked
// targets for the session.
StringSet linkedTargets = snapSession.getLinkedTargets();
if ((linkedTargets == null) || (!linkedTargets.contains(snapshotURI.toString()))) {
BlockSnapshot snapshot = dbClient.queryObject(BlockSnapshot.class, snapshotURI);
// If rollback was successful the snapshot would already have been
// marked inactive, so be sure to check for null.
if ((snapshot != null) && (!snapshot.getInactive())) {
snapshot.setInactive(true);
dbClient.updateObject(snapshot);
}
}
}
}
setErrorOnDataObject(dbClient, BlockSnapshotSession.class, getId(), coded);
for (BlockObject source : allSources) {
setErrorOnDataObject(dbClient, URIUtil.getModelClass(source.getId()), source.getId(), coded);
}
break;
case ready:
setReadyOnDataObject(dbClient, BlockSnapshotSession.class, getId());
for (BlockObject source : allSources) {
setReadyOnDataObject(dbClient, URIUtil.getModelClass(source.getId()), source);
}
break;
case suspended_error:
setSuspendedErrorOnDataObject(dbClient, BlockSnapshotSession.class, getId(), coded);
for (BlockObject source : allSources) {
setSuspendedErrorOnDataObject(dbClient, URIUtil.getModelClass(source.getId()), source, coded);
}
break;
case suspended_no_error:
setSuspendedNoErrorOnDataObject(dbClient, BlockSnapshotSession.class, getId());
for (BlockObject source : allSources) {
setSuspendedNoErrorOnDataObject(dbClient, URIUtil.getModelClass(source.getId()), source);
}
break;
default:
String errMsg = String.format("Unexpected status %s for completer for task %s", status.name(), getOpId());
s_logger.info(errMsg);
throw DeviceControllerException.exceptions.unexpectedCondition(errMsg);
}
s_logger.info("Done snapshot session create task {} with status: {}", getOpId(), status.name());
} catch (Exception e) {
s_logger.error("Failed updating status for snapshot session create task {}", getOpId(), e);
} finally {
super.complete(dbClient, status, coded);
}
}
/**
* {@inheritDoc}
*/
@Override
protected String getDescriptionOfResults(Operation.Status status, BlockObject sourceObj, BlockSnapshotSession snapSession) {
return (status == Operation.Status.ready) ?
String.format(SNAPSHOT_SESSION_CREATE_SUCCESS_MSG, snapSession.getLabel(), sourceObj.getLabel()) :
String.format(SNAPSHOT_SESSION_CREATE_FAIL_MSG, snapSession.getLabel(), sourceObj.getLabel());
}
}