/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.smis.vmax;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.CREATE_GROUP_REPLICA;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.DELETE_GROUP;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.JOB;
import static java.text.MessageFormat.format;
import javax.cim.CIMArgument;
import javax.cim.CIMInstance;
import javax.cim.CIMObjectPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.BlockObject;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.exceptions.DeviceControllerErrors;
import com.emc.storageos.exceptions.DeviceControllerException;
import com.emc.storageos.svcs.errorhandling.model.ServiceError;
import com.emc.storageos.volumecontroller.TaskCompleter;
import com.emc.storageos.volumecontroller.impl.ControllerUtils;
import com.emc.storageos.volumecontroller.impl.smis.CIMObjectPathFactory;
import com.emc.storageos.volumecontroller.impl.smis.ReplicationUtils;
import com.emc.storageos.volumecontroller.impl.smis.SmisCommandHelper;
import com.emc.storageos.volumecontroller.impl.smis.SmisConstants;
import com.emc.storageos.volumecontroller.impl.smis.SmisConstants.SYNC_TYPE;
import com.emc.storageos.volumecontroller.impl.smis.SmisException;
import com.emc.storageos.volumecontroller.impl.smis.SmisUtils;
import com.emc.storageos.volumecontroller.impl.utils.ConsistencyGroupUtils;
/**
* Utils for consistency group related operations for snapshot and clone
*
*/
public class VmaxGroupOperationsUtils {
private static final Logger _log = LoggerFactory.getLogger(VmaxGroupOperationsUtils.class);
/**
* This will create the replica using the target group
*
* @param storage - StorageSystem where the snapshot will be done
* @param groupName - Name of the source group
* @param replicaLabel - Label for the replicas
* @param targetGroupPath - TargetGroup where the snaps will be placed
* @param createInactive - whether the snapshot needs to to be created with sync_active=true/false
* @param taskCompleter - Completer object used for task status update
* @param syncType - sync type, e.g. snapshot or clone
* @param dbClient
* @param helper - smisCommandHelper
* @param cimPath - CIMObjectPathFactory
* @throws DeviceControllerException
*/
public static CIMObjectPath internalCreateGroupReplica(StorageSystem storage, String groupName,
String replicaLabel,
CIMObjectPath targetGroupPath,
boolean createInactive,
TaskCompleter taskCompleter,
SYNC_TYPE syncType,
DbClient dbClient,
SmisCommandHelper helper,
CIMObjectPathFactory cimPath) throws DeviceControllerException {
return internalCreateGroupReplica(storage, groupName, replicaLabel, targetGroupPath, createInactive, false,
taskCompleter, syncType, dbClient, helper, cimPath);
}
public static CIMObjectPath internalCreateGroupReplica(StorageSystem storage, String groupName,
String replicaLabel,
CIMObjectPath targetGroupPath,
boolean createInactive, boolean thinProvisioning,
TaskCompleter taskCompleter,
SYNC_TYPE syncType,
DbClient dbClient,
SmisCommandHelper helper,
CIMObjectPathFactory cimPath) throws DeviceControllerException {
CIMObjectPath job = null;
try {
CIMObjectPath cgPath = cimPath.getReplicationGroupPath(storage, groupName);
CIMObjectPath replicationSvc = cimPath.getControllerReplicationSvcPath(storage);
CIMInstance replicaSettingData = null;
CIMObjectPath targetPoolPath = null;
if (syncType == SYNC_TYPE.CLONE && storage.checkIfVmax3() && ControllerUtils.isVmaxUsing81SMIS(storage, dbClient)) {
/**
* VMAX3 using SMI 8.1 provider needs to send DesiredCopyMethodology=32770
* to create TimeFinder differential clone.
*/
replicaSettingData = ReplicationUtils.getReplicationSettingForSMIS81TFGroupClones(storage, helper,
cimPath, createInactive);
} else if (storage.checkIfVmax3() && syncType != SYNC_TYPE.MIRROR) {
String instanceId = targetGroupPath.getKey(SmisConstants.CP_INSTANCE_ID).getValue().toString();
replicaLabel = SmisUtils.getTargetGroupName(instanceId, storage.getUsingSmis80());
// Unlike single volume snapshot where snapSettingName is used in SMI-S as StorageSynchronized.EMCRelationshipName,
// for group snapshot, GroupSynchronized.RelationshipName is set via RelationshipName input argument of CreateGroupReplica
// method.
// Using replicaLabel in the call below is not necessary, just for convenience.
// But it has to be used in the getCreateGroupReplicaInputArgumentsForVMAX below.
replicaSettingData = helper.getReplicationSettingData(storage, replicaLabel, true);
} else if (syncType == SYNC_TYPE.CLONE) {
replicaSettingData = ReplicationUtils.getReplicationSettingForGroupClones(storage, helper,
cimPath, createInactive);
} else if (syncType == SYNC_TYPE.MIRROR) {
replicaSettingData = ReplicationUtils.getReplicationSettingForGroupMirrors(storage, helper, cimPath);
} else {
replicaSettingData = ReplicationUtils.getReplicationSettingForGroupSnapshots(storage, helper, cimPath, thinProvisioning);
targetPoolPath = ReplicationUtils.getTargetPoolForVPSnapCreation(storage, groupName, null, thinProvisioning, dbClient,
helper, cimPath);
}
CIMArgument[] inArgs = helper.getCreateGroupReplicaInputArgumentsForVMAX(storage, cgPath, createInactive, replicaLabel,
targetGroupPath, targetPoolPath,
replicaSettingData, syncType);
CIMArgument[] outArgs = new CIMArgument[5];
helper.invokeMethod(storage, replicationSvc, CREATE_GROUP_REPLICA, inArgs, outArgs);
job = cimPath.getCimObjectPathFromOutputArgs(outArgs, JOB);
} catch (Exception e) {
_log.info("Problem making SMI-S call: ", e);
// setInactive(((BlockSnapshotCreateCompleter)taskCompleter).getSnapshotURIs(), true);
taskCompleter.error(dbClient, SmisException.errors.methodFailed(CREATE_GROUP_REPLICA, e.getMessage()));
throw new SmisException("Error when creating group replica", e);
}
return job;
}
/**
* Deletes a target group represented by the given target group path
*
* @param storage - StorageSystem where the target group is
* @param targetGroupPath - Path representing target group to be deleted
*
* @throws DeviceControllerException
*/
public static void deleteTargetDeviceGroup(final StorageSystem storage, final CIMObjectPath targetGroupPath,
final DbClient dbClient, final SmisCommandHelper helper, final CIMObjectPathFactory cimPath) {
_log.info(format("Removing target device group {0} from storage system {1}", targetGroupPath, storage.getId()));
try {
CIMObjectPath replicationSvc = cimPath.getControllerReplicationSvcPath(storage);
CIMArgument[] outArgs = new CIMArgument[5];
CIMArgument[] inArgs = helper.getDeleteReplicationGroupInputArguments(storage, targetGroupPath, true);
helper.invokeMethod(storage, replicationSvc, DELETE_GROUP, inArgs, outArgs);
} catch (Exception e) {
_log.error(
format("An error occurred when removing target device group {0} from storage system {1}", targetGroupPath,
storage.getId()), e);
}
}
/**
* This interface is for the group replica active. The created replica may have done
* whatever is necessary to setup the replic for this call. The goal is to
* make this a quick operation and the create operation has already done a lot
* of the "heavy lifting".
*
* @param storage [required] - StorageSystem object representing the array
* @param sourceVolume [required] - source of the replication
* @param blockObj [required] - target of the replication
* @param syncType [required] - either snapshot, or clone
* @param taskCompleter - TaskCompleter object used for the updating operation status.
* @return isSuccess - true: the operation is successful; false: the operation fails
*
*/
public static boolean activateGroupReplicas(final StorageSystem storage,
final BlockObject sourceVolume,
final BlockObject blockObj,
final SYNC_TYPE syncType,
final TaskCompleter taskCompleter,
final DbClient dbClient,
final SmisCommandHelper helper,
final CIMObjectPathFactory cimPath) throws Exception {
boolean isSuccess = false;
String groupName = ConsistencyGroupUtils.getSourceConsistencyGroupName(sourceVolume, dbClient);
String replicaGroupName = blockObj.getReplicationGroupInstance();
CIMObjectPath groupSynchronized = cimPath.getGroupSynchronizedPath(storage, groupName, replicaGroupName);
CIMArgument[] inArgs = null;
if (helper.checkExists(storage, groupSynchronized, false, false) != null) {
if (syncType == SYNC_TYPE.SNAPSHOT) {
inArgs = helper.getActivateGroupSnapshotInputArguments(storage, groupSynchronized);
} else if (syncType == SYNC_TYPE.CLONE) {
inArgs = helper.getActivateGroupFullCopyInputArguments(storage, groupSynchronized);
}
CIMArgument[] outArgs = new CIMArgument[5];
helper.callModifyReplica(storage, inArgs, outArgs);
isSuccess = true;
} else {
ServiceError error = DeviceControllerErrors.smis.unableToFindSynchPath(groupName);
taskCompleter.error(dbClient, error);
}
return isSuccess;
}
}