/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.smis;
import static com.emc.storageos.volumecontroller.impl.smis.ReplicationUtils.callEMCRefreshIfRequired;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.COPY_BEFORE_ACTIVATE;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.COPY_STATE_RESTORED_INT_VALUE;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.CREATE_NEW_TARGET_VALUE;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.DIFFERENTIAL_CLONE_VALUE;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.GET_DEFAULT_REPLICATION_SETTING_DATA;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.PROVISIONING_TARGET_SAME_AS_SOURCE;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.SMIS810_TF_DIFFERENTIAL_CLONE_VALUE;
import static com.emc.storageos.volumecontroller.impl.smis.SmisConstants.TARGET_ELEMENT_SUPPLIER;
import static javax.cim.CIMDataType.UINT16_T;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import javax.cim.CIMArgument;
import javax.cim.CIMInstance;
import javax.cim.CIMObjectPath;
import javax.cim.CIMProperty;
import javax.cim.UnsignedInteger16;
import javax.wbem.CloseableIterator;
import javax.wbem.WBEMException;
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.BlockSnapshot;
import com.emc.storageos.db.client.model.DiscoveredDataObject.Type;
import com.emc.storageos.db.client.model.NamedURI;
import com.emc.storageos.db.client.model.Operation;
import com.emc.storageos.db.client.model.StoragePool;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.TenantOrg;
import com.emc.storageos.db.client.model.Volume;
import com.emc.storageos.db.client.model.Volume.ReplicationState;
import com.emc.storageos.db.client.util.NameGenerator;
import com.emc.storageos.db.client.util.NullColumnValueGetter;
import com.emc.storageos.exceptions.DeviceControllerErrors;
import com.emc.storageos.exceptions.DeviceControllerException;
import com.emc.storageos.exceptions.DeviceControllerExceptions;
import com.emc.storageos.svcs.errorhandling.model.ServiceCoded;
import com.emc.storageos.svcs.errorhandling.model.ServiceError;
import com.emc.storageos.volumecontroller.CloneOperations;
import com.emc.storageos.volumecontroller.TaskCompleter;
import com.emc.storageos.volumecontroller.impl.ControllerServiceImpl;
import com.emc.storageos.volumecontroller.impl.ControllerUtils;
import com.emc.storageos.volumecontroller.impl.job.QueueJob;
import com.emc.storageos.volumecontroller.impl.smis.job.SmisBlockResyncSnapshotJob;
import com.emc.storageos.volumecontroller.impl.smis.job.SmisCloneRestoreJob;
import com.emc.storageos.volumecontroller.impl.smis.job.SmisCloneResyncJob;
import com.emc.storageos.volumecontroller.impl.smis.job.SmisCloneVolumeJob;
public class AbstractCloneOperations implements CloneOperations {
private static final Logger _log = LoggerFactory.getLogger(AbstractCloneOperations.class);
private static final String CREATE_ERROR_MSG_FORMAT = "from %s to %s";
protected static final String ACTIVATE_ERROR_MSG_FORMAT = "Failed to activate full copy %s";
private static final String DETACH_ERROR_MSG_FORMAT = "Failed to detach full copy %s from source %s";
private static final String RESYNC_ERROR_MSG_FORMAT = "Failed to resync full copy %s";
private static final String FRACTURE_ERROR_MSG_FORMAT = "Failed to fracture full copy %s from source %s";
protected DbClient _dbClient;
protected SmisCommandHelper _helper;
protected CIMObjectPathFactory _cimPath;
protected NameGenerator _nameGenerator;
public void setCimObjectPathFactory(CIMObjectPathFactory cimObjectPathFactory) {
_cimPath = cimObjectPathFactory;
}
public void setDbClient(DbClient dbClient) {
_dbClient = dbClient;
}
public void setSmisCommandHelper(SmisCommandHelper smisCommandHelper) {
_helper = smisCommandHelper;
}
public void setNameGenerator(NameGenerator nameGenerator) {
_nameGenerator = nameGenerator;
}
@Override
@SuppressWarnings("rawtypes")
public void createSingleClone(StorageSystem storageSystem, URI sourceVolume, URI cloneVolume,
Boolean createInactive, TaskCompleter taskCompleter) {
_log.info("START createSingleClone operation");
try {
BlockObject sourceObj = BlockObject.fetch(_dbClient, sourceVolume);
URI tenantUri = null;
Volume baseVolume = null;
boolean isSourceSnap = false;
if (sourceObj instanceof BlockSnapshot) {
// In case of snapshot, get the tenant from its parent volume
NamedURI parentVolUri = ((BlockSnapshot) sourceObj).getParent();
Volume parentVolume = _dbClient.queryObject(Volume.class, parentVolUri);
tenantUri = parentVolume.getTenant().getURI();
baseVolume = parentVolume;
isSourceSnap = true;
} else {
// This is a default flow
tenantUri = ((Volume) sourceObj).getTenant().getURI();
baseVolume = (Volume) sourceObj;
}
// CTRL-1992: Need to resync any existing snapshot restore sessions, if applicable
if (_helper.arraySupportsResync(storageSystem)) {
CloseableIterator<CIMObjectPath> syncObjectIter =
_cimPath.getSyncObjects(storageSystem, sourceObj);
CIMObjectPath path = null;
while (syncObjectIter.hasNext()) {
path = syncObjectIter.next();
CIMInstance instance =
_helper.getInstance(storageSystem, path, false, false,
SmisConstants.PS_COPY_STATE_AND_DESC_SYNCTYPE);
String copyState =
instance.getPropertyValue(SmisConstants.CP_COPY_STATE).
toString();
String copyStateDesc =
instance.getPropertyValue(SmisConstants.
EMC_COPY_STATE_DESC).toString();
String syncType = instance.getPropertyValue(SmisConstants.CP_SYNC_TYPE).
toString();
_log.info(String.format("Sync %s has copyState %s (%s) syncType %s",
path.toString(), copyState, copyStateDesc, syncType));
if (copyState.equals(COPY_STATE_RESTORED_INT_VALUE) &&
syncType.equals(Integer.toString(SmisConstants.SNAPSHOT_VALUE))) {
// This snapshot is in the 'Restored' state, need to
// resync it, before we can create a full copy
_log.info("Sync {} is in restored state, need to resync",
path);
SmisBlockResyncSnapshotJob job =
new SmisBlockResyncSnapshotJob(null, storageSystem.getId(),
new TaskCompleter() {
@Override
protected void
complete(DbClient dbClient,
Operation.Status status,
ServiceCoded coded) throws DeviceControllerException {
}
});
CIMArgument[] result = new CIMArgument[5];
_helper.invokeMethodSynchronously(storageSystem,
_cimPath.getControllerReplicationSvcPath(storageSystem),
SmisConstants.MODIFY_REPLICA_SYNCHRONIZATION,
_helper.getResyncSnapshotInputArguments(path),
result, job);
if (job.isSuccess()) {
_log.info("{} was successfully resynchronized", path.toString());
} else {
_log.error("Encountered a failure while trying to resynchronize a restored snapshot");
ServiceError error = DeviceControllerErrors.smis.
resyncActiveRestoreSessionFailure(sourceObj.getLabel());
taskCompleter.error(_dbClient, error);
return;
}
}
}
}
Volume cloneObj = _dbClient.queryObject(Volume.class, cloneVolume);
StoragePool targetPool = _dbClient.queryObject(StoragePool.class, cloneObj.getPool());
TenantOrg tenantOrg = _dbClient.queryObject(TenantOrg.class, tenantUri);
String cloneLabel = generateLabel(tenantOrg, cloneObj);
CIMObjectPath volumeGroupPath = _helper.getVolumeGroupPath(storageSystem, storageSystem, baseVolume, targetPool);
CIMObjectPath sourceVolumePath = _cimPath.getBlockObjectPath(storageSystem, sourceObj);
CIMObjectPath replicationSvcPath = _cimPath.getControllerReplicationSvcPath(storageSystem);
CIMArgument[] inArgs = null;
CIMInstance repSettingData = null;
if (storageSystem.deviceIsType(Type.vmax)) {
if (createInactive && storageSystem.getUsingSmis80()) {
repSettingData = _helper.getReplicationSettingDataInstanceForDesiredCopyMethod(storageSystem, COPY_BEFORE_ACTIVATE,
true);
} else if (storageSystem.checkIfVmax3() && ControllerUtils.isVmaxUsing81SMIS(storageSystem, _dbClient)) {
/**
* VMAX3 using SMI 8.1 provider needs to send DesiredCopyMethodology=32770
* to create TimeFinder differential clone.
*/
repSettingData = _helper.getReplicationSettingDataInstanceForDesiredCopyMethod(storageSystem,
SMIS810_TF_DIFFERENTIAL_CLONE_VALUE, true);
} else {
repSettingData = _helper.getReplicationSettingDataInstanceForDesiredCopyMethod(storageSystem, DIFFERENTIAL_CLONE_VALUE,
true);
}
inArgs = _helper.getCloneInputArguments(cloneLabel, sourceVolumePath, volumeGroupPath, storageSystem,
targetPool, createInactive, repSettingData);
} else if (storageSystem.deviceIsType(Type.vnxblock)) {
if (!isSourceSnap) {
repSettingData = getReplicationSettingDataInstanceForThinProvisioningPolicy(storageSystem,
PROVISIONING_TARGET_SAME_AS_SOURCE);
// don't supply target pool when using thinlyProvisioningPolicy=PROVISIONING_TARGET_SAME_AS_SOURCE
inArgs = _helper.getCreateElementReplicaMirrorInputArgumentsWithReplicationSettingData(storageSystem, sourceObj, null,
false, repSettingData, cloneLabel);
cloneObj.setPool(baseVolume.getPool());
_dbClient.persistObject(cloneObj);
} else {
// when source is snapshot, create clone instead of mirror, since creating mirror from a snap is not supported.
inArgs = _helper.getCloneInputArguments(cloneLabel, sourceVolumePath, volumeGroupPath, storageSystem,
targetPool, createInactive, null);
}
}
CIMArgument[] outArgs = new CIMArgument[5];
_helper.invokeMethod(storageSystem, replicationSvcPath, SmisConstants.CREATE_ELEMENT_REPLICA, inArgs, outArgs);
CIMObjectPath job = _cimPath.getCimObjectPathFromOutputArgs(outArgs, SmisConstants.JOB);
if (job != null) {
ControllerServiceImpl.enqueueJob(new QueueJob(new SmisCloneVolumeJob(job, storageSystem.getId(),
taskCompleter)));
}
} catch (Exception e) {
Volume clone = _dbClient.queryObject(Volume.class, cloneVolume);
if (clone != null) {
clone.setInactive(true);
_dbClient.persistObject(clone);
}
String errorMsg = String.format(CREATE_ERROR_MSG_FORMAT, sourceVolume, cloneVolume);
_log.error(errorMsg, e);
SmisException serviceCode = DeviceControllerExceptions.smis.createFullCopyFailure(errorMsg, e);
taskCompleter.error(_dbClient, serviceCode);
throw serviceCode;
}
}
@Override
@SuppressWarnings("rawtypes")
public void detachSingleClone(StorageSystem storageSystem, URI cloneVolume,
TaskCompleter taskCompleter) {
_log.info("START detachSingleClone operation");
Volume clone = null;
try {
callEMCRefreshIfRequired(_dbClient, _helper, storageSystem,
Arrays.asList(cloneVolume));
clone = _dbClient.queryObject(Volume.class, cloneVolume);
URI sourceUri = clone.getAssociatedSourceVolume();
if (!NullColumnValueGetter.isNullURI(sourceUri)) {
BlockObject sourceObj = BlockObject.fetch(_dbClient, sourceUri);
if (sourceObj != null) {
StorageSystem sourceSystem = _dbClient.queryObject(StorageSystem.class, sourceObj.getStorageController());
CIMObjectPath syncObject = _cimPath.getStorageSynchronized(sourceSystem, sourceObj, storageSystem, clone);
CIMInstance instance = _helper.checkExists(storageSystem, syncObject, false, false);
if (instance != null) {
CIMArgument[] inArgs = _helper.getDetachSynchronizationInputArguments(syncObject);
CIMArgument[] outArgs = new CIMArgument[5];
_helper.callModifyReplica(storageSystem, inArgs, outArgs);
} else {
_log.info("The clone is already detached. Detach will not be performed.");
}
} else {
_log.info("The clone's source volume cannot be found in the database. Detach will not be performed.");
}
} else {
_log.info("The clone does not have a source volume. Detach will not be performed.");
}
// Update sync active property
/**
* cq:609984 - No need to reset sync active flag as its caused problem
* when check for activated target volume.
*
* @see <code>BlockService#activateFullCopy
* volume.setSyncActive(false);
*/
ReplicationUtils.removeDetachedFullCopyFromSourceFullCopiesList(clone, _dbClient);
clone.setAssociatedSourceVolume(NullColumnValueGetter.getNullURI());
clone.setReplicaState(ReplicationState.DETACHED.name());
_dbClient.persistObject(clone);
if (taskCompleter != null) {
taskCompleter.ready(_dbClient);
}
} catch (Exception e) {
String errorMsg = String.format(DETACH_ERROR_MSG_FORMAT, cloneVolume, clone.getAssociatedSourceVolume());
_log.error(errorMsg, e);
if (taskCompleter != null) {
taskCompleter.error(_dbClient, DeviceControllerException.exceptions.detachVolumeFullCopyFailed(e));
}
}
}
@Override
@SuppressWarnings("rawtypes")
public void activateSingleClone(StorageSystem storageSystem, URI fullCopy, TaskCompleter completer) {
_log.info("START activateSingleClone for {}", fullCopy);
try {
Volume volume = _dbClient.queryObject(Volume.class, fullCopy);
CIMArgument[] inArgs = _helper.getActivateFullCopyArguments(storageSystem, volume);
CIMArgument[] outArgs = new CIMArgument[5];
_helper.callModifyReplica(storageSystem, inArgs, outArgs);
// Update sync active property
volume.setSyncActive(true);
volume.setRefreshRequired(true);
volume.setReplicaState(ReplicationState.SYNCHRONIZED.name());
_dbClient.persistObject(volume);
completer.ready(_dbClient);
_log.info("FINISH activateSingleClone for {}", fullCopy);
} catch (Exception e) {
String errorMsg = String.format(ACTIVATE_ERROR_MSG_FORMAT, fullCopy);
_log.error(errorMsg, e);
completer.error(_dbClient, DeviceControllerException.exceptions.activateVolumeFullCopyFailed(e));
}
}
@Override
@SuppressWarnings("rawtypes")
public void fractureSingleClone(StorageSystem storageSystem, URI source, URI cloneVolume,
TaskCompleter taskCompleter) {
_log.info("START fractureSingleClone operation");
Volume clone = null;
try {
callEMCRefreshIfRequired(_dbClient, _helper, storageSystem,
Arrays.asList(cloneVolume));
clone = _dbClient.queryObject(Volume.class, cloneVolume);
URI sourceUri = clone.getAssociatedSourceVolume();
if (!NullColumnValueGetter.isNullURI(sourceUri)) {
BlockObject sourceObj = BlockObject.fetch(_dbClient, sourceUri);
if (sourceObj != null) {
StorageSystem sourceSystem = _dbClient.queryObject(StorageSystem.class, sourceObj.getStorageController());
CIMObjectPath syncObject = _cimPath.getStorageSynchronized(sourceSystem, sourceObj, storageSystem, clone);
CIMInstance instance = _helper.checkExists(storageSystem, syncObject, false, false);
if (instance != null) {
fractureReplica(storageSystem, syncObject);
} else {
String errorMsg = "The clone is already detached. fracture will not be performed.";
_log.info(errorMsg);
ServiceError error = DeviceControllerErrors.smis.methodFailed("fractureSingleClone", errorMsg);
taskCompleter.error(_dbClient, error);
}
} else {
String errorMsg = "The clone's source volume cannot be found in the database. Fractrure will not be performed.";
_log.info(errorMsg);
ServiceError error = DeviceControllerErrors.smis.methodFailed("fractureSingleClone", errorMsg);
taskCompleter.error(_dbClient, error);
}
} else {
String errorMsg = "The clone does not have a source volume. Fracture will not be performed.";
_log.info(errorMsg);
ServiceError error = DeviceControllerErrors.smis.methodFailed("fractureSingleClone", errorMsg);
taskCompleter.error(_dbClient, error);
}
clone.setReplicaState(ReplicationState.SYNCHRONIZED.name());
_dbClient.persistObject(clone);
taskCompleter.ready(_dbClient);
} catch (Exception e) {
String errorMsg = String.format(FRACTURE_ERROR_MSG_FORMAT, cloneVolume, clone.getAssociatedSourceVolume());
_log.error(errorMsg, e);
taskCompleter.error(_dbClient, DeviceControllerException.exceptions.fractureFullCopyFailed(e));
}
}
@Override
@SuppressWarnings("rawtypes")
public void resyncSingleClone(StorageSystem storageSystem, URI cloneVolume,
TaskCompleter taskCompleter) {
_log.info("START resyncSingleClone operation");
Volume clone = null;
try {
callEMCRefreshIfRequired(_dbClient, _helper, storageSystem,
Arrays.asList(cloneVolume));
clone = _dbClient.queryObject(Volume.class, cloneVolume);
URI sourceUri = clone.getAssociatedSourceVolume();
Volume sourceObj = _dbClient.queryObject(Volume.class, sourceUri);
StorageSystem sourceSystem = _dbClient.queryObject(StorageSystem.class, sourceObj.getStorageController());
CIMObjectPath syncObject = _cimPath.getStorageSynchronized(sourceSystem, sourceObj, storageSystem, clone);
CIMInstance instance = _helper.checkExists(storageSystem, syncObject, false, false);
if (instance != null) {
CIMArgument[] inArgs = _helper.getResyncReplicaInputArguments(syncObject);
CIMArgument[] outArgs = new CIMArgument[5];
_helper.callModifyReplica(storageSystem, inArgs, outArgs);
CIMObjectPath job = _cimPath.getCimObjectPathFromOutputArgs(outArgs, SmisConstants.JOB);
if (job != null) {
ControllerServiceImpl.enqueueJob(new QueueJob(new SmisCloneResyncJob(job, storageSystem.getId(),
taskCompleter)));
}
} else {
String errorMsg = "The clone is already detached. resync will not be performed.";
_log.info(errorMsg);
ServiceError error = DeviceControllerErrors.smis.methodFailed("resyncSingleClone", errorMsg);
taskCompleter.error(_dbClient, error);
}
} catch (Exception e) {
String errorMsg = String.format(RESYNC_ERROR_MSG_FORMAT, cloneVolume);
_log.error(errorMsg, e);
taskCompleter.error(_dbClient, DeviceControllerException.exceptions.resynchronizeFullCopyFailed(e));
}
}
@Override
public void createGroupClone(StorageSystem storage, List<URI> cloneList,
Boolean createInactive, TaskCompleter taskCompleter) throws DeviceControllerException {
throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported();
}
protected String generateLabel(TenantOrg tenantOrg, Volume cloneObj) {
return _nameGenerator.generate(tenantOrg.getLabel(), cloneObj.getLabel(), cloneObj.getId().toString(), '-',
SmisConstants.MAX_VOLUME_NAME_LENGTH);
}
@SuppressWarnings("rawtypes")
private CIMInstance getReplicationSettingDataInstanceForThinProvisioningPolicy(final StorageSystem storageSystem, int desiredValue) {
CIMInstance modifiedInstance = null;
try {
CIMObjectPath replicationSettingCapabilities = _cimPath
.getReplicationServiceCapabilitiesPath(storageSystem);
CIMArgument[] inArgs = _helper.getReplicationSettingDataInstance();
CIMArgument[] outArgs = new CIMArgument[5];
_helper.invokeMethod(storageSystem, replicationSettingCapabilities,
GET_DEFAULT_REPLICATION_SETTING_DATA, inArgs, outArgs);
for (CIMArgument<?> outArg : outArgs) {
if (null == outArg) {
continue;
}
if (outArg.getName().equalsIgnoreCase(SmisConstants.DEFAULT_INSTANCE)) {
CIMInstance repInstance = (CIMInstance) outArg.getValue();
if (null != repInstance) {
CIMProperty<?> thinProvisioningPolicy = new CIMProperty<Object>(SmisConstants.THIN_PROVISIONING_POLICY, UINT16_T,
new UnsignedInteger16(desiredValue));
CIMProperty<?> targetElementSupplier = new CIMProperty<Object>(TARGET_ELEMENT_SUPPLIER,
UINT16_T, new UnsignedInteger16(CREATE_NEW_TARGET_VALUE));
CIMProperty<?>[] propArray = new CIMProperty<?>[] { thinProvisioningPolicy, targetElementSupplier };
modifiedInstance = repInstance.deriveInstance(propArray);
break;
}
}
}
} catch (Exception e) {
_log.error("Error retrieving Replication Setting Data Instance ", e);
}
return modifiedInstance;
}
@Override
public void activateGroupClones(StorageSystem storage, List<URI> clone, TaskCompleter taskCompleter) {
throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported();
}
@Override
public void fractureGroupClones(StorageSystem storage, List<URI> clones, TaskCompleter completer) {
throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported();
}
@Override
public void detachGroupClones(StorageSystem storage, List<URI> clones, TaskCompleter completer) {
throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported();
}
@Override
public void establishVolumeCloneGroupRelation(StorageSystem storage, URI sourceVolume, URI clone, TaskCompleter completer) {
throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported();
}
/**
* Implementation for restoring of a single volume clone restore.
*
* @param storage [required] - StorageSystem object representing the array
* @param volume [required] - Volume URI for the volume to be restored
* @param clone [required] - URI representing the previously created clone
* @param taskCompleter - TaskCompleter object used for the updating operation status.
*/
@Override
@SuppressWarnings("rawtypes")
public void restoreFromSingleClone(StorageSystem storage, URI clone, TaskCompleter taskCompleter) throws DeviceControllerException {
_log.info("START restore Single clone operation");
try {
callEMCRefreshIfRequired(_dbClient, _helper, storage, Arrays.asList(clone));
Volume cloneVol = _dbClient.queryObject(Volume.class, clone);
Volume originalVol = _dbClient.queryObject(Volume.class, cloneVol.getAssociatedSourceVolume());
CIMObjectPath syncObjectPath = _cimPath.getStorageSynchronized(storage, originalVol, storage, cloneVol);
if (_helper.checkExists(storage, syncObjectPath, false, false) != null) {
CIMArgument[] outArgs = new CIMArgument[5];
CIMArgument[] inArgs = _helper.getRestoreFromReplicaInputArgumentsWithForce(syncObjectPath);
_helper.callModifyReplica(storage, inArgs, outArgs);
CIMObjectPath job = _cimPath.getCimObjectPathFromOutputArgs(outArgs, SmisConstants.JOB);
if (job != null) {
ControllerServiceImpl.enqueueJob(new QueueJob(new SmisCloneRestoreJob(job,
storage.getId(), taskCompleter)));
}
} else {
ServiceError error = DeviceControllerErrors.smis.unableToFindSynchPath(storage.getLabel());
taskCompleter.error(_dbClient, error);
}
} catch (WBEMException e) {
String message = String.format("Error encountered when trying to restore from clone %s on array %s",
clone.toString(), storage.getSerialNumber());
_log.error(message, e);
ServiceError error = DeviceControllerErrors.smis.unableToCallStorageProvider(e.getMessage());
taskCompleter.error(_dbClient, error);
} catch (Exception e) {
String message = String.format("Generic exception when trying to restore from clone %s on array %s",
clone.toString(), storage.getSerialNumber());
_log.error(message, e);
taskCompleter.error(_dbClient, DeviceControllerException.exceptions.restoreVolumeFromFullCopyFailed(e));
}
}
@Override
public void restoreGroupClones(StorageSystem storage, List<URI> clones, TaskCompleter taskCompleter) throws DeviceControllerException {
throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported();
}
@Override
public void resyncGroupClones(StorageSystem storage, List<URI> clones, TaskCompleter taskCompleter) throws DeviceControllerException {
throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported();
}
protected void fractureReplica(StorageSystem storageSystem, CIMObjectPath syncObject) throws WBEMException {
CIMArgument[] inArgs = _helper.getFractureMirrorInputArgumentsWithCopyState(syncObject, null);
CIMArgument[] outArgs = new CIMArgument[5];
_helper.callModifyReplica(storageSystem, inArgs, outArgs);
}
}