/* * Copyright (c) 2008-2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.smis.ibm.xiv; import java.net.URI; import java.util.List; import javax.cim.CIMArgument; 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.BlockSnapshot; import com.emc.storageos.db.client.model.NamedURI; 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.DeviceControllerException; import com.emc.storageos.exceptions.DeviceControllerExceptions; import com.emc.storageos.volumecontroller.CloneOperations; import com.emc.storageos.volumecontroller.TaskCompleter; import com.emc.storageos.volumecontroller.impl.block.taskcompleter.CloneCreateCompleter; import com.emc.storageos.volumecontroller.impl.smis.ReplicationUtils; import com.emc.storageos.volumecontroller.impl.smis.SmisConstants; import com.emc.storageos.volumecontroller.impl.smis.SmisException; import com.emc.storageos.volumecontroller.impl.smis.ibm.IBMCIMObjectPathFactory; public class XIVCloneOperations implements CloneOperations { private static final Logger _log = LoggerFactory .getLogger(XIVCloneOperations.class); private static final String CREATE_ERROR_MSG_FORMAT = "from %s to %s"; private DbClient _dbClient; private XIVSmisCommandHelper _helper; private IBMCIMObjectPathFactory _cimPath; private NameGenerator _nameGenerator; private XIVSmisStorageDevicePostProcessor _smisStorageDevicePostProcessor; public void setCimObjectPathFactory( IBMCIMObjectPathFactory cimObjectPathFactory) { _cimPath = cimObjectPathFactory; } public void setDbClient(DbClient dbClient) { _dbClient = dbClient; } public void setSmisCommandHelper(XIVSmisCommandHelper smisCommandHelper) { _helper = smisCommandHelper; } public void setNameGenerator(NameGenerator nameGenerator) { _nameGenerator = nameGenerator; } public void setSmisStorageDevicePostProcessor( final XIVSmisStorageDevicePostProcessor smisStorageDevicePostProcessor) { _smisStorageDevicePostProcessor = smisStorageDevicePostProcessor; } @SuppressWarnings("rawtypes") @Override public void createSingleClone(StorageSystem storageSystem, URI sourceVolume, URI cloneVolume, Boolean createInactive, TaskCompleter taskCompleter) { _log.info("START createSingleClone operation"); SmisException serviceCode = null; CIMArgument[] outArgs = new CIMArgument[5]; try { BlockObject sourceObj = BlockObject.fetch(_dbClient, sourceVolume); URI tenantUri = null; 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(); } else { tenantUri = ((Volume) sourceObj).getTenant().getURI(); } Volume cloneObj = _dbClient.queryObject(Volume.class, cloneVolume); StoragePool targetPool = _dbClient.queryObject(StoragePool.class, cloneObj.getPool()); TenantOrg tenantOrg = _dbClient.queryObject(TenantOrg.class, tenantUri); String cloneLabel = _nameGenerator.generate(tenantOrg.getLabel(), cloneObj.getLabel(), cloneObj.getId().toString(), '-', SmisConstants.MAX_VOLUME_NAME_LENGTH); CIMObjectPath sourceVolumePath = _cimPath.getBlockObjectPath( storageSystem, sourceObj); CIMArgument[] inArgs = _helper .getCloneInputArguments(cloneLabel, sourceVolumePath, storageSystem, targetPool, createInactive); _helper.callReplicationSvc(storageSystem, SmisConstants.CREATE_ELEMENT_REPLICA, inArgs, outArgs); } catch (Exception e) { String errorMsg = String.format(CREATE_ERROR_MSG_FORMAT, sourceVolume, cloneVolume); _log.error(errorMsg, e); serviceCode = DeviceControllerExceptions.smis .createFullCopyFailure(errorMsg, e); } finally { try { // update clone and pool // clone will be set to inactive if no return from provider _smisStorageDevicePostProcessor.processCloneCreation(storageSystem, cloneVolume, outArgs, (CloneCreateCompleter) taskCompleter); } catch (Exception e) { String errorMsg = "Exception on creating clone of " + sourceVolume; _log.error(errorMsg, e); // set serviceCode only if no previous exception if (serviceCode == null) { serviceCode = DeviceControllerExceptions.smis.createFullCopyFailure(errorMsg, e); } } if (serviceCode != null) { taskCompleter.error(_dbClient, serviceCode); throw serviceCode; } } } @Override public void activateSingleClone(StorageSystem storageSystem, URI fullCopy, TaskCompleter taskCompleter) { _log.info("START activateSingleClone operation"); // no operation, set to ready taskCompleter.ready(_dbClient); } @Override public void detachSingleClone(StorageSystem storageSystem, URI cloneVolume, TaskCompleter taskCompleter) { _log.info("START detachSingleClone operation"); // no operation, set to ready Volume clone = _dbClient.queryObject(Volume.class, cloneVolume); ReplicationUtils.removeDetachedFullCopyFromSourceFullCopiesList(clone, _dbClient); clone.setReplicaState(ReplicationState.DETACHED.name()); clone.setAssociatedSourceVolume(NullColumnValueGetter.getNullURI()); _dbClient.persistObject(clone); taskCompleter.ready(_dbClient); } @Override public void restoreFromSingleClone(StorageSystem storageSystem, URI clone, TaskCompleter completer) { _log.info("START restoreFromSingleClone operation"); // no operation, set to ready completer.ready(_dbClient); } @Override public void fractureSingleClone(StorageSystem storageSystem, URI sourceVolume, URI clone, TaskCompleter completer) { _log.info("START fractureSingleClone operation"); // no operation, set to ready completer.ready(_dbClient); } @Override public void resyncSingleClone(StorageSystem storageSystem, URI clone, TaskCompleter completer) { _log.info("START resyncSingleClone operation"); // no operation, set to ready completer.ready(_dbClient); } @Override public void createGroupClone(StorageSystem storage, List<URI> cloneList, Boolean createInactive, TaskCompleter taskCompleter) { // no operation, set to ready taskCompleter.ready(_dbClient); } @Override public void activateGroupClones(StorageSystem storage, List<URI> clone, TaskCompleter taskCompleter) { throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported(); } @Override public void restoreGroupClones(StorageSystem storageSystem, List<URI> clone, TaskCompleter completer) { throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported(); } @Override public void fractureGroupClones(StorageSystem storageSystem, List<URI> clone, TaskCompleter completer) { throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported(); } @Override public void resyncGroupClones(StorageSystem storageSystem, List<URI> clone, TaskCompleter completer) { throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported(); } @Override public void detachGroupClones(StorageSystem storageSystem, List<URI> clone, TaskCompleter completer) { throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported(); } @Override public void establishVolumeCloneGroupRelation(StorageSystem storage, URI sourceVolume, URI clone, TaskCompleter completer) { throw DeviceControllerException.exceptions.blockDeviceOperationNotSupported(); } }