mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Create a template from a SAN snapshot
This commit is contained in:
parent
b576e4d67e
commit
455ffc3342
@ -135,6 +135,10 @@ public class TemplateObjectTO implements DataTO {
|
||||
return this.imageDataStore;
|
||||
}
|
||||
|
||||
public void setHypervisorType(Hypervisor.HypervisorType hypervisorType) {
|
||||
this.hypervisorType = hypervisorType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hypervisor.HypervisorType getHypervisorType() {
|
||||
return this.hypervisorType;
|
||||
|
||||
@ -32,4 +32,6 @@
|
||||
class="org.apache.cloudstack.storage.motion.XenServerStorageMotionStrategy" />
|
||||
<bean id="hypervStorageMotionStrategy"
|
||||
class="org.apache.cloudstack.storage.motion.HypervStorageMotionStrategy" />
|
||||
<bean id="storageSystemDataMotionStrategy"
|
||||
class="org.apache.cloudstack.storage.motion.StorageSystemDataMotionStrategy" />
|
||||
</beans>
|
||||
|
||||
@ -18,8 +18,12 @@
|
||||
*/
|
||||
package org.apache.cloudstack.storage.motion;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -27,20 +31,68 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
|
||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.org.Cluster;
|
||||
import com.cloud.org.Grouping.AllocationState;
|
||||
import com.cloud.resource.ResourceState;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.dao.SnapshotDetailsDao;
|
||||
import com.cloud.storage.dao.SnapshotDetailsVO;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
|
||||
@Component
|
||||
public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
private static final Logger s_logger = Logger.getLogger(StorageSystemDataMotionStrategy.class);
|
||||
|
||||
@Inject private AgentManager _agentMgr;
|
||||
@Inject private ConfigurationDao _configDao;
|
||||
@Inject private HostDao _hostDao;
|
||||
@Inject private ManagementService _mgr;
|
||||
@Inject private PrimaryDataStoreDao _storagePoolDao;
|
||||
@Inject private SnapshotDetailsDao _snapshotDetailsDao;
|
||||
@Inject private VolumeService _volService;
|
||||
|
||||
@Override
|
||||
public StrategyPriority canHandle(DataObject srcData, DataObject destData) {
|
||||
return StrategyPriority.DEFAULT;
|
||||
if (srcData instanceof SnapshotInfo && destData.getDataStore().getRole() == DataStoreRole.Image || destData.getDataStore().getRole() == DataStoreRole.ImageCache) {
|
||||
DataStore dataStore = srcData.getDataStore();
|
||||
Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities();
|
||||
|
||||
if (mapCapabilities != null) {
|
||||
String value = mapCapabilities.get(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString());
|
||||
Boolean supportsStorageSystemSnapshots = new Boolean(value);
|
||||
|
||||
if (supportsStorageSystemSnapshots) {
|
||||
s_logger.info("Using 'StorageSystemDataMotionStrategy'");
|
||||
|
||||
return StrategyPriority.HIGHEST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return StrategyPriority.CANT_HANDLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,10 +102,114 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
@Override
|
||||
public Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||
if (srcData instanceof SnapshotInfo && destData.getDataStore().getRole() == DataStoreRole.Image || destData.getDataStore().getRole() == DataStoreRole.ImageCache) {
|
||||
SnapshotInfo snapshotInfo = (SnapshotInfo)srcData;
|
||||
HostVO hostVO = getHost(srcData);
|
||||
DataStore srcDataStore = srcData.getDataStore();
|
||||
|
||||
String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
||||
int primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
||||
CopyCommand copyCommand = new CopyCommand(srcData.getTO(), destData.getTO(), primaryStorageDownloadWait, VirtualMachineManager.ExecuteInSequence.value());
|
||||
|
||||
CopyCmdAnswer copyCmdAnswer = null;
|
||||
|
||||
try {
|
||||
_volService.grantAccess(snapshotInfo, hostVO, srcDataStore);
|
||||
|
||||
Map<String, String> srcDetails = getSourceDetails(_storagePoolDao.findById(srcDataStore.getId()), snapshotInfo);
|
||||
|
||||
copyCommand.setOptions(srcDetails);
|
||||
|
||||
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new CloudRuntimeException(ex.getMessage());
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
_volService.revokeAccess(snapshotInfo, hostVO, srcDataStore);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
s_logger.debug(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
String errMsg = null;
|
||||
|
||||
if (copyCmdAnswer == null || !copyCmdAnswer.getResult()) {
|
||||
if (copyCmdAnswer != null && copyCmdAnswer.getDetails() != null && !copyCmdAnswer.getDetails().isEmpty()) {
|
||||
errMsg = copyCmdAnswer.getDetails();
|
||||
}
|
||||
else {
|
||||
errMsg = "Unable to perform host-side operation";
|
||||
}
|
||||
}
|
||||
|
||||
CopyCommandResult result = new CopyCommandResult(null, copyCmdAnswer);
|
||||
|
||||
result.setResult(errMsg);
|
||||
|
||||
callback.complete(result);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, String> getSourceDetails(StoragePoolVO storagePoolVO, SnapshotInfo snapshotInfo) {
|
||||
Map<String, String> srcDetails = new HashMap<String, String>();
|
||||
|
||||
srcDetails.put(DiskTO.STORAGE_HOST, storagePoolVO.getHostAddress());
|
||||
srcDetails.put(DiskTO.STORAGE_PORT, String.valueOf(storagePoolVO.getPort()));
|
||||
|
||||
long snapshotId = snapshotInfo.getId();
|
||||
|
||||
srcDetails.put(DiskTO.IQN, getProperty(snapshotId, DiskTO.IQN));
|
||||
|
||||
srcDetails.put(DiskTO.CHAP_INITIATOR_USERNAME, getProperty(snapshotId, DiskTO.CHAP_INITIATOR_USERNAME));
|
||||
srcDetails.put(DiskTO.CHAP_INITIATOR_SECRET, getProperty(snapshotId, DiskTO.CHAP_INITIATOR_SECRET));
|
||||
srcDetails.put(DiskTO.CHAP_TARGET_USERNAME, getProperty(snapshotId, DiskTO.CHAP_TARGET_USERNAME));
|
||||
srcDetails.put(DiskTO.CHAP_TARGET_SECRET, getProperty(snapshotId, DiskTO.CHAP_TARGET_SECRET));
|
||||
|
||||
return srcDetails;
|
||||
}
|
||||
|
||||
private String getProperty(long snapshotId, String property) {
|
||||
SnapshotDetailsVO snapshotDetails = _snapshotDetailsDao.findDetail(snapshotId, property);
|
||||
|
||||
if (snapshotDetails != null) {
|
||||
return snapshotDetails.getValue();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public HostVO getHost(DataObject srcData) {
|
||||
long dataStoreId = srcData.getDataStore().getId();
|
||||
StoragePoolVO storagePoolVO = _storagePoolDao.findById(dataStoreId);
|
||||
|
||||
List<? extends Cluster> clusters = _mgr.searchForClusters(storagePoolVO.getDataCenterId(), new Long(0), Long.MAX_VALUE, HypervisorType.XenServer.toString());
|
||||
|
||||
if (clusters == null) {
|
||||
throw new CloudRuntimeException("Unable to locate an applicable cluster");
|
||||
}
|
||||
|
||||
for (Cluster cluster : clusters) {
|
||||
if (cluster.getAllocationState() == AllocationState.Enabled) {
|
||||
List<HostVO> hosts = _hostDao.findByClusterId(cluster.getId());
|
||||
|
||||
if (hosts != null) {
|
||||
for (HostVO host : hosts) {
|
||||
if (host.getResourceState() == ResourceState.Enabled) {
|
||||
return host;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new CloudRuntimeException("Unable to locate an applicable cluster");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||
return copyAsync(srcData, destData, null, callback);
|
||||
|
||||
@ -217,6 +217,9 @@ public class TemplateObject implements TemplateInfo {
|
||||
// For template created from snapshot, template name is determine by resource code.
|
||||
templateVO.setUniqueName(newTemplate.getName());
|
||||
}
|
||||
if (newTemplate.getHypervisorType() != null) {
|
||||
templateVO.setHypervisorType(newTemplate.getHypervisorType());
|
||||
}
|
||||
templateVO.setSize(newTemplate.getSize());
|
||||
imageDao.update(templateVO.getId(), templateVO);
|
||||
}
|
||||
|
||||
@ -226,7 +226,7 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase {
|
||||
sourceDetails = getSourceDetails(volumeInfo);
|
||||
}
|
||||
|
||||
HostVO hostVO = getHostId(hostId, volumeVO);
|
||||
HostVO hostVO = getHost(hostId, volumeVO);
|
||||
|
||||
long storagePoolId = volumeVO.getPoolId();
|
||||
StoragePoolVO storagePoolVO = _storagePoolDao.findById(storagePoolId);
|
||||
@ -340,7 +340,7 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
private HostVO getHostId(Long hostId, VolumeVO volumeVO) {
|
||||
private HostVO getHost(Long hostId, VolumeVO volumeVO) {
|
||||
HostVO hostVO = _hostDao.findById(hostId);
|
||||
|
||||
if (hostVO != null) {
|
||||
@ -404,7 +404,8 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase {
|
||||
DataStore dataStore = _dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary);
|
||||
|
||||
Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities();
|
||||
if(mapCapabilities != null) {
|
||||
|
||||
if (mapCapabilities != null) {
|
||||
String value = mapCapabilities.get(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString());
|
||||
Boolean supportsStorageSystemSnapshots = new Boolean(value);
|
||||
|
||||
@ -412,6 +413,7 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase {
|
||||
return StrategyPriority.HIGHEST;
|
||||
}
|
||||
}
|
||||
|
||||
return StrategyPriority.CANT_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,8 +64,10 @@ import com.cloud.agent.api.to.S3TO;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.agent.api.to.SwiftTO;
|
||||
import com.cloud.exception.InternalErrorException;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase.SRType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.resource.StorageProcessor;
|
||||
import com.cloud.utils.S3Utils;
|
||||
@ -1457,7 +1459,126 @@ public class XenServerStorageProcessor implements StorageProcessor {
|
||||
|
||||
@Override
|
||||
public Answer createTemplateFromSnapshot(CopyCommand cmd) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
|
||||
SnapshotObjectTO snapshotObjTO = (SnapshotObjectTO)cmd.getSrcTO();
|
||||
TemplateObjectTO templateObjTO = (TemplateObjectTO)cmd.getDestTO();
|
||||
|
||||
if (!(snapshotObjTO.getDataStore() instanceof PrimaryDataStoreTO) || !(templateObjTO.getDataStore() instanceof NfsTO)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String userSpecifiedTemplateName = templateObjTO.getName();
|
||||
|
||||
NfsTO destStore = null;
|
||||
URI destUri = null;
|
||||
|
||||
try {
|
||||
destStore = (NfsTO)templateObjTO.getDataStore();
|
||||
|
||||
destUri = new URI(destStore.getUrl());
|
||||
} catch (Exception ex) {
|
||||
s_logger.debug("Invalid URI", ex);
|
||||
|
||||
return new CopyCmdAnswer("Invalid URI: " + ex.toString());
|
||||
}
|
||||
|
||||
SR srcSr = null;
|
||||
SR destSr = null;
|
||||
|
||||
String destDir = templateObjTO.getPath();
|
||||
VDI destVdi = null;
|
||||
|
||||
boolean result = false;
|
||||
|
||||
try {
|
||||
Map<String, String> srcDetails = cmd.getOptions();
|
||||
|
||||
String iScsiName = srcDetails.get(DiskTO.IQN);
|
||||
String storageHost = srcDetails.get(DiskTO.STORAGE_HOST);
|
||||
String chapInitiatorUsername = srcDetails.get(DiskTO.CHAP_INITIATOR_USERNAME);
|
||||
String chapInitiatorSecret = srcDetails.get(DiskTO.CHAP_INITIATOR_SECRET);
|
||||
|
||||
srcSr = hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, true);
|
||||
|
||||
String destNfsPath = destUri.getHost() + ":" + destUri.getPath();
|
||||
|
||||
if (!hypervisorResource.createSecondaryStorageFolder(conn, destNfsPath, destDir)) {
|
||||
String details = " Failed to create folder " + destDir + " in secondary storage";
|
||||
|
||||
s_logger.warn(details);
|
||||
|
||||
return new CopyCmdAnswer(details);
|
||||
}
|
||||
|
||||
URI templateUri = new URI(destStore.getUrl() + "/" + destDir);
|
||||
|
||||
destSr = hypervisorResource.createNfsSRbyURI(conn, templateUri, false);
|
||||
|
||||
// there should only be one VDI in this SR
|
||||
VDI srcVdi = srcSr.getVDIs(conn).iterator().next();
|
||||
|
||||
destVdi = srcVdi.copy(conn, destSr);
|
||||
|
||||
// scan makes XenServer pick up VDI physicalSize
|
||||
destSr.scan(conn);
|
||||
|
||||
if (userSpecifiedTemplateName != null) {
|
||||
destVdi.setNameLabel(conn, userSpecifiedTemplateName);
|
||||
}
|
||||
|
||||
String templateUuid = destVdi.getUuid(conn);
|
||||
String templateFilename = templateUuid + ".vhd";
|
||||
long virtualSize = destVdi.getVirtualSize(conn);
|
||||
long physicalSize = destVdi.getPhysicalUtilisation(conn);
|
||||
|
||||
// create the template.properties file
|
||||
String templatePath = destNfsPath + "/" + destDir;
|
||||
|
||||
templatePath = templatePath.replaceAll("//", "/");
|
||||
|
||||
result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, userSpecifiedTemplateName, null,
|
||||
physicalSize, virtualSize, templateObjTO.getId());
|
||||
|
||||
if (!result) {
|
||||
throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + templateUri);
|
||||
}
|
||||
|
||||
TemplateObjectTO newTemplate = new TemplateObjectTO();
|
||||
|
||||
newTemplate.setPath(destDir + "/" + templateFilename);
|
||||
newTemplate.setFormat(Storage.ImageFormat.VHD);
|
||||
newTemplate.setHypervisorType(HypervisorType.XenServer);
|
||||
newTemplate.setSize(virtualSize);
|
||||
newTemplate.setPhysicalSize(physicalSize);
|
||||
newTemplate.setName(templateUuid);
|
||||
|
||||
result = true;
|
||||
|
||||
return new CopyCmdAnswer(newTemplate);
|
||||
} catch (Exception ex) {
|
||||
s_logger.error("Failed to create a template from a snapshot", ex);
|
||||
|
||||
return new CopyCmdAnswer("Failed to create a template from a snapshot: " + ex.toString());
|
||||
} finally {
|
||||
if (!result) {
|
||||
if (destVdi != null) {
|
||||
try {
|
||||
destVdi.destroy(conn);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Cleaned up leftover VDI on destination storage due to failure: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (srcSr != null) {
|
||||
hypervisorResource.removeSR(conn, srcSr);
|
||||
}
|
||||
|
||||
if (destSr != null) {
|
||||
hypervisorResource.removeSR(conn, destSr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -61,69 +61,94 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
|
||||
public Xenserver625StorageProcessor(CitrixResourceBase resource) {
|
||||
super(resource);
|
||||
}
|
||||
|
||||
protected boolean mountNfs(Connection conn, String remoteDir, String localDir) {
|
||||
if (localDir == null) {
|
||||
localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remoteDir.getBytes());
|
||||
}
|
||||
|
||||
String results = hypervisorResource.callHostPluginAsync(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", 100 * 1000,
|
||||
"localDir", localDir, "remoteDir", remoteDir);
|
||||
|
||||
if (results == null || results.isEmpty()) {
|
||||
String errMsg = "Could not mount secondary storage " + remoteDir + " on host " + localDir;
|
||||
|
||||
s_logger.warn(errMsg);
|
||||
|
||||
throw new CloudRuntimeException(errMsg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean makeDirectory(Connection conn, String path) {
|
||||
String result = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "makeDirectory", "path", path);
|
||||
|
||||
if (result == null || result.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected SR createFileSR(Connection conn, String path) {
|
||||
SR sr = null;
|
||||
PBD pbd = null;
|
||||
|
||||
try {
|
||||
String srname = hypervisorResource.getHost().uuid + path.trim();
|
||||
|
||||
Set<SR> srs = SR.getByNameLabel(conn, srname);
|
||||
if ( srs != null && !srs.isEmpty()) {
|
||||
|
||||
if (srs != null && !srs.isEmpty()) {
|
||||
return srs.iterator().next();
|
||||
}
|
||||
|
||||
Map<String, String> smConfig = new HashMap<String, String>();
|
||||
|
||||
Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid);
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
sr = SR.introduce(conn, uuid, srname, srname, "file", "file", false, smConfig);
|
||||
|
||||
PBD.Record record = new PBD.Record();
|
||||
|
||||
record.host = host;
|
||||
record.SR = sr;
|
||||
|
||||
smConfig.put("location", path);
|
||||
|
||||
record.deviceConfig = smConfig;
|
||||
|
||||
pbd = PBD.create(conn, record);
|
||||
|
||||
pbd.plug(conn);
|
||||
|
||||
sr.scan(conn);
|
||||
|
||||
return sr;
|
||||
} catch (Exception e) {
|
||||
} catch (Exception ex) {
|
||||
try {
|
||||
if (pbd != null) {
|
||||
pbd.destroy(conn);
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
s_logger.debug("Failed to destroy pbd", e);
|
||||
s_logger.debug("Failed to destroy PBD", ex);
|
||||
}
|
||||
|
||||
try {
|
||||
if (sr != null) {
|
||||
sr.forget(conn);
|
||||
}
|
||||
} catch (Exception e2) {
|
||||
s_logger.error("Failed to forget sr", e);
|
||||
s_logger.error("Failed to forget SR", ex);
|
||||
}
|
||||
String msg = "createFileSR failed! due to " + e.toString();
|
||||
s_logger.warn(msg, e);
|
||||
throw new CloudRuntimeException(msg, e);
|
||||
|
||||
String msg = "createFileSR failed! due to the following: " + ex.toString();
|
||||
|
||||
s_logger.warn(msg, ex);
|
||||
|
||||
throw new CloudRuntimeException(msg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user