/*
* Copyright (c) 2012-2015 iWave Software LLC
* All Rights Reserved
*/
package com.emc.sa.service.vipr.block;
import static com.emc.sa.service.ServiceParams.DIRECT_ACCESS;
import static com.emc.sa.service.ServiceParams.FAILOVER_TARGET;
import static com.emc.sa.service.ServiceParams.IMAGE_TO_ACCESS;
import static com.emc.sa.service.ServiceParams.POINT_IN_TIME;
import static com.emc.sa.service.ServiceParams.STORAGE_TYPE;
import static com.emc.sa.service.ServiceParams.VOLUMES;
import static com.emc.vipr.client.core.util.ResourceUtils.stringId;
import java.net.URI;
import com.emc.sa.asset.providers.BlockProvider;
import com.emc.sa.engine.ExecutionUtils;
import com.emc.sa.engine.bind.Param;
import com.emc.sa.engine.service.Service;
import com.emc.sa.service.vipr.ViPRService;
import com.emc.sa.service.vipr.block.tasks.FailoverBlockConsistencyGroup;
import com.emc.sa.service.vipr.block.tasks.FailoverBlockVolume;
import com.emc.sa.service.vipr.block.tasks.UpdateBlockConsistencyGroupAccessMode;
import com.emc.sa.service.vipr.block.tasks.UpdateBlockVolumeAccessMode;
import com.emc.storageos.model.DataObjectRestRep;
import com.emc.storageos.model.block.BlockConsistencyGroupRestRep;
import com.emc.storageos.model.block.BlockObjectRestRep;
import com.emc.storageos.model.block.Copy;
import com.emc.storageos.model.varray.VirtualArrayRestRep;
import com.emc.vipr.client.Tasks;
@Service("FailoverBlockVolume")
public class FailoverBlockVolumeService extends ViPRService {
// constant representing the RP type.
private static final String RECOVER_POINT = "rp";
@Param(value = STORAGE_TYPE, required = false)
protected String storageType;
@Param(VOLUMES)
protected URI protectionSource;
@Param(FAILOVER_TARGET)
protected URI protectionTarget;
@Param(value = IMAGE_TO_ACCESS, required = false)
protected String imageToAccess;
@Param(value = POINT_IN_TIME, required = false)
protected String pointInTime;
@Param(value = DIRECT_ACCESS, required = false)
protected Boolean directAccess;
private String type;
@Override
public void precheck() {
String sourceId = "";
String targetId = "";
String targetName = "";
String sourceName = "";
if (ConsistencyUtils.isVolumeStorageType(storageType)) {
// The type selected is volume
BlockObjectRestRep targetVolume = BlockStorageUtils.getVolume(protectionTarget);
BlockObjectRestRep sourceVolume = BlockStorageUtils.getVolume(protectionSource);
type = BlockStorageUtils.getFailoverType(targetVolume);
targetId = stringId(targetVolume);
targetName = targetVolume.getName();
sourceId = stringId(sourceVolume);
sourceName = sourceVolume.getName();
} else {
// The type selected is consistency group
BlockConsistencyGroupRestRep cg = BlockStorageUtils.getBlockConsistencyGroup(protectionSource);
VirtualArrayRestRep virtualArray = BlockStorageUtils.getVirtualArray(protectionTarget);
type = ConsistencyUtils.getFailoverType(cg);
targetId = stringId(virtualArray);
targetName = virtualArray.getName();
sourceId = stringId(cg);
sourceName = cg.getName();
}
if (type == null) {
ExecutionUtils.fail("failTask.FailoverBlockVolumeService", args(sourceId, targetId), args());
}
if (type.equals(RECOVER_POINT) && BlockProvider.PIT_IMAGE_OPTION_KEY.equals(imageToAccess) && pointInTime == null) {
ExecutionUtils.fail("failTask.FailoverBlockVolumeService.pit", new Object[] {}, new Object[] {});
}
// TODO: Add new fields
logInfo("fail.over.block.volume.service", type.toUpperCase(), sourceName, targetName);
}
@Override
public void execute() {
Tasks<? extends DataObjectRestRep> failoverTasks = null;
Tasks<? extends DataObjectRestRep> updateAccessModeTasks = null;
if (ConsistencyUtils.isVolumeStorageType(storageType)) {
// The type selected is volume
if (type != null && type.equals(RECOVER_POINT) && BlockProvider.PIT_IMAGE_OPTION_KEY.equals(imageToAccess)) {
// This is a RP failover request so we need to pass along the copyName and pointInTime values.
// We only want to do this if the image selected is NOT the latest image (this is handled by
// the default case) but a specific snapshot or point in time.
setImageToAccessForRP();
failoverTasks = execute(new FailoverBlockVolume(protectionSource, protectionTarget, type, pointInTime));
} else {
failoverTasks = execute(new FailoverBlockVolume(protectionSource, protectionTarget, type));
}
} else {
// The type selected is consistency group
if (type != null && type.equals(RECOVER_POINT) && (BlockProvider.PIT_IMAGE_OPTION_KEY.equals(imageToAccess))) {
// This is a RP failover request so we need to pass along the copyName and pointInTime values.
// We only want to do this if the image selected is NOT the latest image (this is handled by
// the default case) but a specific snapshot or point in time.
setImageToAccessForRP();
failoverTasks = execute(new FailoverBlockConsistencyGroup(protectionSource, protectionTarget, type, pointInTime));
} else {
failoverTasks = execute(new FailoverBlockConsistencyGroup(protectionSource, protectionTarget, type));
}
}
// Only call update access mode to direct access for RecoverPoint
if (Boolean.TRUE.equals(directAccess) && type != null && type.equals(RECOVER_POINT)) {
if (ConsistencyUtils.isVolumeStorageType(storageType)) {
// Update the access mode on the target copy to direct access
updateAccessModeTasks = execute(new UpdateBlockVolumeAccessMode(protectionSource, protectionTarget, type,
Copy.ImageAccessMode.DIRECT_ACCESS.name()));
} else {
// Update the access mode on the target copy to direct access
updateAccessModeTasks = execute(new UpdateBlockConsistencyGroupAccessMode(protectionSource, protectionTarget, type,
Copy.ImageAccessMode.DIRECT_ACCESS.name()));
}
}
if (failoverTasks != null) {
addAffectedResources(failoverTasks);
}
if (updateAccessModeTasks != null) {
addAffectedResources(updateAccessModeTasks);
}
}
/**
* Determines the appropriate image to access (copy) value for RecoverPoint failover.
*/
private void setImageToAccessForRP() {
if (BlockProvider.PIT_IMAGE_OPTION_KEY.equals(imageToAccess)) {
// If the image to access is a point-in-time, null out the image access variable otherwise
// the failover over logic will attempt to look for a bookmark called 'pit'.
imageToAccess = null;
}
}
}