mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
refactor data motion service for volumes
This commit is contained in:
parent
79151f5f5d
commit
4029e7af44
@ -18,20 +18,26 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.cloudstack.engine.subsystem.api.storage;
|
package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
|
||||||
public class CreateCmdResult extends CommandResult {
|
public class CreateCmdResult extends CommandResult {
|
||||||
private String path;
|
private String path;
|
||||||
private Long size;
|
private Answer answer;
|
||||||
public CreateCmdResult(String path, Long size) {
|
public CreateCmdResult(String path, Answer answer) {
|
||||||
super();
|
super();
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.size = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPath() {
|
public String getPath() {
|
||||||
return this.path;
|
return this.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getSize() {
|
public Answer getAnswer() {
|
||||||
return this.size;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAnswer(Answer answer) {
|
||||||
|
this.answer = answer;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ public class TemplateObjectTO implements DataTO {
|
|||||||
private String path;
|
private String path;
|
||||||
private String uuid;
|
private String uuid;
|
||||||
private DiskFormat diskType;
|
private DiskFormat diskType;
|
||||||
private ImageStoreTO imageDataStore;
|
private DataStoreTO imageDataStore;
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
public TemplateObjectTO() {
|
public TemplateObjectTO() {
|
||||||
@ -38,7 +38,7 @@ public class TemplateObjectTO implements DataTO {
|
|||||||
this.path = template.getUri();
|
this.path = template.getUri();
|
||||||
this.uuid = template.getUuid();
|
this.uuid = template.getUuid();
|
||||||
//this.diskType = template.getDiskType();
|
//this.diskType = template.getDiskType();
|
||||||
this.imageDataStore = new ImageStoreTO((ImageStoreInfo)template.getDataStore());
|
this.imageDataStore = template.getDataStore().getTO();
|
||||||
this.name = template.getUniqueName();
|
this.name = template.getUniqueName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ public class TemplateObjectTO implements DataTO {
|
|||||||
return this.diskType;
|
return this.diskType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageStoreTO getImageDataStore() {
|
public DataStoreTO getImageDataStore() {
|
||||||
return this.imageDataStore;
|
return this.imageDataStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,16 +18,17 @@ package org.apache.cloudstack.storage.to;
|
|||||||
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
|
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType;
|
import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.to.DataStoreTO;
|
||||||
|
|
||||||
public class VolumeObjectTO implements DataTO {
|
public class VolumeObjectTO implements DataTO {
|
||||||
private String uuid;
|
private String uuid;
|
||||||
private VolumeType volumeType;
|
private VolumeType volumeType;
|
||||||
private DiskFormat diskType;
|
private DiskFormat diskType;
|
||||||
private PrimaryDataStoreTO dataStore;
|
private DataStoreTO dataStore;
|
||||||
private String name;
|
private String name;
|
||||||
private long size;
|
private long size;
|
||||||
private String path;
|
private String path;
|
||||||
@ -42,7 +43,7 @@ public class VolumeObjectTO implements DataTO {
|
|||||||
//this.volumeType = volume.getType();
|
//this.volumeType = volume.getType();
|
||||||
//this.diskType = volume.getDiskType();
|
//this.diskType = volume.getDiskType();
|
||||||
if (volume.getDataStore() != null) {
|
if (volume.getDataStore() != null) {
|
||||||
this.dataStore = new PrimaryDataStoreTO((PrimaryDataStoreInfo)volume.getDataStore());
|
this.dataStore = volume.getDataStore().getTO();
|
||||||
} else {
|
} else {
|
||||||
this.dataStore = null;
|
this.dataStore = null;
|
||||||
}
|
}
|
||||||
@ -66,7 +67,7 @@ public class VolumeObjectTO implements DataTO {
|
|||||||
return this.diskType;
|
return this.diskType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrimaryDataStoreTO getDataStore() {
|
public DataStoreTO getDataStore() {
|
||||||
return this.dataStore;
|
return this.dataStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -141,47 +141,24 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
|
|
||||||
@DB
|
@DB
|
||||||
protected Answer copyVolumeFromImage(DataObject srcData, DataObject destData) {
|
protected Answer copyVolumeFromImage(DataObject srcData, DataObject destData) {
|
||||||
String value = configDao.getValue(Config.RecreateSystemVmEnabled.key());
|
String value = configDao.getValue(Config.CopyVolumeWait.key());
|
||||||
int _copyvolumewait = NumbersUtil.parseInt(value,
|
int _copyvolumewait = NumbersUtil.parseInt(value,
|
||||||
Integer.parseInt(Config.CopyVolumeWait.getDefaultValue()));
|
Integer.parseInt(Config.CopyVolumeWait.getDefaultValue()));
|
||||||
|
|
||||||
VolumeDataStoreVO volumeStoreVO = volumeStoreDao.findByVolume(srcData
|
if (srcData.getDataStore().getRole() != DataStoreRole.ImageCache && destData.getDataStore().getRole() != DataStoreRole.ImageCache) {
|
||||||
.getId());
|
//need to copy it to image cache store
|
||||||
DataStore srcStore = srcData.getDataStore();
|
DataObject cacheData = cacheMgr.createCacheObject(srcData, destData.getDataStore().getScope());
|
||||||
String[] volumePath = volumeStoreVO.getInstallPath().split("/");
|
CopyCommand cmd = new CopyCommand(cacheData.getTO(), destData.getTO(), _copyvolumewait);
|
||||||
String volumeUUID = volumePath[volumePath.length - 1].split("\\.")[0];
|
EndPoint ep = selector.select(cacheData, destData);
|
||||||
StoragePool destPool = (StoragePool) destData.getDataStore();
|
Answer answer = ep.sendMessage(cmd);
|
||||||
CopyVolumeCommand cvCmd = new CopyVolumeCommand(srcData.getId(),
|
return answer;
|
||||||
volumeUUID, destPool, srcStore.getUri(), false,
|
} else {
|
||||||
_copyvolumewait);
|
//handle copy it to/from cache store
|
||||||
CopyVolumeAnswer cvAnswer = null;
|
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _copyvolumewait);
|
||||||
String errMsg = null;
|
EndPoint ep = selector.select(srcData, destData);
|
||||||
try {
|
Answer answer = ep.sendMessage(cmd);
|
||||||
cvAnswer = (CopyVolumeAnswer) this.storageMgr.sendToPool(destPool,
|
return answer;
|
||||||
cvCmd);
|
|
||||||
} catch (StorageUnavailableException e1) {
|
|
||||||
s_logger.debug("Failed to copy volume " + srcData.getId() + " to "
|
|
||||||
+ destData.getId(), e1);
|
|
||||||
errMsg = e1.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cvAnswer == null || !cvAnswer.getResult()) {
|
|
||||||
errMsg = cvAnswer.getDetails();
|
|
||||||
}
|
|
||||||
|
|
||||||
VolumeVO vol = this.volDao.findById(destData.getId());
|
|
||||||
Transaction txn = Transaction.currentTxn();
|
|
||||||
txn.start();
|
|
||||||
vol.setPath(cvAnswer.getVolumePath());
|
|
||||||
vol.setFolder(destPool.getPath());
|
|
||||||
vol.setPodId(destPool.getPodId());
|
|
||||||
vol.setPoolId(destPool.getId());
|
|
||||||
vol.setPodId(destPool.getPodId());
|
|
||||||
|
|
||||||
this.volDao.update(vol.getId(), vol);
|
|
||||||
volumeStoreDao.remove(volumeStoreVO.getId());
|
|
||||||
txn.commit();
|
|
||||||
return cvAnswer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Answer copyTemplate(DataObject srcData, DataObject destData) {
|
private Answer copyTemplate(DataObject srcData, DataObject destData) {
|
||||||
@ -195,7 +172,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
Answer answer = ep.sendMessage(cmd);
|
Answer answer = ep.sendMessage(cmd);
|
||||||
return answer;
|
return answer;
|
||||||
} else {
|
} else {
|
||||||
//handle copy it to cache store
|
//handle copy it to/from cache store
|
||||||
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _primaryStorageDownloadWait);
|
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _primaryStorageDownloadWait);
|
||||||
EndPoint ep = selector.select(srcData, destData);
|
EndPoint ep = selector.select(srcData, destData);
|
||||||
Answer answer = ep.sendMessage(cmd);
|
Answer answer = ep.sendMessage(cmd);
|
||||||
@ -326,56 +303,15 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Answer copyVolumeBetweenPools(DataObject srcData, DataObject destData) {
|
protected Answer copyVolumeBetweenPools(DataObject srcData, DataObject destData) {
|
||||||
VolumeInfo volume = (VolumeInfo)srcData;
|
String value = configDao.getValue(Config.CopyVolumeWait.key());
|
||||||
VolumeInfo destVolume = (VolumeInfo)destData;
|
|
||||||
String secondaryStorageURL = this.templateMgr.getSecondaryStorageURL(volume
|
|
||||||
.getDataCenterId());
|
|
||||||
StoragePool srcPool = (StoragePool)this.dataStoreMgr.getDataStore(volume
|
|
||||||
.getPoolId(), DataStoreRole.Primary);
|
|
||||||
|
|
||||||
StoragePool destPool = (StoragePool)this.dataStoreMgr.getDataStore(destVolume.getPoolId(), DataStoreRole.Primary);
|
|
||||||
|
|
||||||
String value = this.configDao.getValue(Config.CopyVolumeWait.toString());
|
|
||||||
int _copyvolumewait = NumbersUtil.parseInt(value,
|
int _copyvolumewait = NumbersUtil.parseInt(value,
|
||||||
Integer.parseInt(Config.CopyVolumeWait.getDefaultValue()));
|
Integer.parseInt(Config.CopyVolumeWait.getDefaultValue()));
|
||||||
CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(),
|
|
||||||
volume.getPath(), srcPool, secondaryStorageURL, true,
|
|
||||||
_copyvolumewait);
|
|
||||||
CopyVolumeAnswer cvAnswer;
|
|
||||||
try {
|
|
||||||
cvAnswer = (CopyVolumeAnswer) this.storageMgr.sendToPool(srcPool, cvCmd);
|
|
||||||
} catch (StorageUnavailableException e1) {
|
|
||||||
throw new CloudRuntimeException(
|
|
||||||
"Failed to copy the volume from the source primary storage pool to secondary storage.",
|
|
||||||
e1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cvAnswer == null || !cvAnswer.getResult()) {
|
DataObject cacheData = cacheMgr.createCacheObject(srcData, destData.getDataStore().getScope());
|
||||||
throw new CloudRuntimeException(
|
CopyCommand cmd = new CopyCommand(cacheData.getTO(), destData.getTO(), _copyvolumewait);
|
||||||
"Failed to copy the volume from the source primary storage pool to secondary storage.");
|
EndPoint ep = selector.select(cacheData, destData);
|
||||||
}
|
Answer answer = ep.sendMessage(cmd);
|
||||||
|
return answer;
|
||||||
String secondaryStorageVolumePath = cvAnswer.getVolumePath();
|
|
||||||
|
|
||||||
cvCmd = new CopyVolumeCommand(volume.getId(),
|
|
||||||
secondaryStorageVolumePath, destPool,
|
|
||||||
secondaryStorageURL, false, _copyvolumewait);
|
|
||||||
try {
|
|
||||||
cvAnswer = (CopyVolumeAnswer) this.storageMgr.sendToPool(destPool, cvCmd);
|
|
||||||
} catch (StorageUnavailableException e1) {
|
|
||||||
throw new CloudRuntimeException(
|
|
||||||
"Failed to copy the volume from secondary storage to the destination primary storage pool.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cvAnswer == null || !cvAnswer.getResult()) {
|
|
||||||
throw new CloudRuntimeException(
|
|
||||||
"Failed to copy the volume from secondary storage to the destination primary storage pool.");
|
|
||||||
}
|
|
||||||
|
|
||||||
VolumeVO destVol = this.volDao.findById(destVolume.getId());
|
|
||||||
destVol.setPath(cvAnswer.getVolumePath());
|
|
||||||
this.volDao.update(destVol.getId(), destVol);
|
|
||||||
return cvAnswer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -29,10 +29,13 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
|||||||
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
|
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
|
||||||
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||||
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
|
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
|
||||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.storage.DownloadAnswer;
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.storage.DataStoreRole;
|
import com.cloud.storage.DataStoreRole;
|
||||||
import com.cloud.storage.Volume;
|
import com.cloud.storage.Volume;
|
||||||
@ -52,6 +55,8 @@ public class VolumeObject implements VolumeInfo {
|
|||||||
@Inject
|
@Inject
|
||||||
VolumeDao volumeDao;
|
VolumeDao volumeDao;
|
||||||
@Inject
|
@Inject
|
||||||
|
VolumeDataStoreDao volumeStoreDao;
|
||||||
|
@Inject
|
||||||
ObjectInDataStoreManager ojbectInStoreMgr;
|
ObjectInDataStoreManager ojbectInStoreMgr;
|
||||||
private Object payload;
|
private Object payload;
|
||||||
|
|
||||||
@ -357,6 +362,14 @@ public class VolumeObject implements VolumeInfo {
|
|||||||
vol.setSize(newVol.getSize());
|
vol.setSize(newVol.getSize());
|
||||||
volumeDao.update(vol.getId(), vol);
|
volumeDao.update(vol.getId(), vol);
|
||||||
}
|
}
|
||||||
|
} else if (this.dataStore.getRole() == DataStoreRole.Image) {
|
||||||
|
if (answer instanceof DownloadAnswer) {
|
||||||
|
DownloadAnswer dwdAnswer = (DownloadAnswer)answer;
|
||||||
|
VolumeDataStoreVO volStore = this.volumeStoreDao.findByStoreVolume(this.dataStore.getId(), this.getId());
|
||||||
|
volStore.setInstallPath(dwdAnswer.getInstallPath());
|
||||||
|
volStore.setChecksum(dwdAnswer.getCheckSum());
|
||||||
|
this.volumeStoreDao.update(volStore.getId(), volStore);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.processEvent(event);
|
this.processEvent(event);
|
||||||
|
|||||||
@ -621,7 +621,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
srcVolume.processEvent(Event.OperationSuccessed);
|
srcVolume.processEvent(Event.OperationSuccessed);
|
||||||
destVolume.processEvent(Event.OperationSuccessed);
|
destVolume.processEvent(Event.OperationSuccessed, result.getAnswer());
|
||||||
AsyncCallFuture<VolumeApiResult> destroyFuture = this.expungeVolumeAsync(srcVolume);
|
AsyncCallFuture<VolumeApiResult> destroyFuture = this.expungeVolumeAsync(srcVolume);
|
||||||
destroyFuture.get();
|
destroyFuture.get();
|
||||||
future.complete(res);
|
future.complete(res);
|
||||||
@ -639,25 +639,28 @@ public class VolumeServiceImpl implements VolumeService {
|
|||||||
public AsyncCallFuture<VolumeApiResult> registerVolume(VolumeInfo volume, DataStore store) {
|
public AsyncCallFuture<VolumeApiResult> registerVolume(VolumeInfo volume, DataStore store) {
|
||||||
|
|
||||||
AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
|
AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
|
||||||
VolumeObject vo = (VolumeObject) volume;
|
DataObject volumeOnStore = store.create(volume);
|
||||||
|
|
||||||
CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(null, vo, future);
|
volumeOnStore.processEvent(Event.CreateOnlyRequested);
|
||||||
|
|
||||||
|
CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(null, volumeOnStore, future);
|
||||||
AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
|
AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
|
||||||
caller.setCallback(caller.getTarget().registerVolumeCallback(null, null))
|
caller.setCallback(caller.getTarget().registerVolumeCallback(null, null))
|
||||||
.setContext(context);
|
.setContext(context);
|
||||||
|
|
||||||
dataObjectMgr.createAsync(volume, store, caller, true);
|
store.getDriver().createAsync(volumeOnStore, caller);
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Void registerVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeContext<VolumeApiResult> context) {
|
protected Void registerVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeContext<VolumeApiResult> context) {
|
||||||
CreateCmdResult result = callback.getResult();
|
CreateCmdResult result = callback.getResult();
|
||||||
|
|
||||||
VolumeObject vo = (VolumeObject)context.volume;
|
VolumeObject vo = (VolumeObject)context.volume;
|
||||||
/*if (result.isFailed()) {
|
if (result.isFailed()) {
|
||||||
vo.stateTransit(Volume.Event.OperationFailed);
|
vo.processEvent(Event.OperationFailed);
|
||||||
} else {
|
} else {
|
||||||
vo.stateTransit(Volume.Event.OperationSucceeded);
|
vo.processEvent(Event.OperationSuccessed, result.getAnswer());
|
||||||
}*/
|
}
|
||||||
|
|
||||||
_resourceLimitMgr.incrementResourceCount(vo.getAccountId(), ResourceType.secondary_storage,
|
_resourceLimitMgr.incrementResourceCount(vo.getAccountId(), ResourceType.secondary_storage,
|
||||||
vo.getSize());
|
vo.getSize());
|
||||||
|
|||||||
@ -55,12 +55,15 @@ import org.apache.xmlrpc.XmlRpcException;
|
|||||||
|
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
import com.cloud.agent.api.Command;
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.storage.CopyVolumeAnswer;
|
||||||
import com.cloud.agent.api.storage.CreateAnswer;
|
import com.cloud.agent.api.storage.CreateAnswer;
|
||||||
import com.cloud.agent.api.storage.DeleteVolumeCommand;
|
import com.cloud.agent.api.storage.DeleteVolumeCommand;
|
||||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
|
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
|
||||||
import com.cloud.agent.api.to.DataStoreTO;
|
import com.cloud.agent.api.to.DataStoreTO;
|
||||||
|
import com.cloud.agent.api.to.NfsTO;
|
||||||
import com.cloud.agent.api.to.StorageFilerTO;
|
import com.cloud.agent.api.to.StorageFilerTO;
|
||||||
import com.cloud.agent.api.to.VolumeTO;
|
import com.cloud.agent.api.to.VolumeTO;
|
||||||
|
import com.cloud.exception.InternalErrorException;
|
||||||
import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
|
import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
|
||||||
import com.cloud.storage.DataStoreRole;
|
import com.cloud.storage.DataStoreRole;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
@ -776,6 +779,74 @@ public class XenServerStorageResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected Answer copyVolumeFromImageCacheToPrimary(DataTO srcData, DataTO destData, int wait) {
|
||||||
|
Connection conn = hypervisorResource.getConnection();
|
||||||
|
VolumeObjectTO srcVolume = (VolumeObjectTO)srcData;
|
||||||
|
VolumeObjectTO destVolume = (VolumeObjectTO)destData;
|
||||||
|
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destVolume.getDataStore();
|
||||||
|
DataStoreTO srcStore = srcVolume.getDataStore();
|
||||||
|
|
||||||
|
if (srcStore instanceof NfsTO) {
|
||||||
|
NfsTO nfsStore = (NfsTO)srcStore;
|
||||||
|
try {
|
||||||
|
SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
|
||||||
|
String srUuid = primaryStoragePool.getUuid(conn);
|
||||||
|
String volumePath = nfsStore.getUrl() + ":" + srcVolume.getPath();
|
||||||
|
String uuid = copy_vhd_from_secondarystorage(conn, volumePath, srUuid, wait );
|
||||||
|
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||||
|
newVol.setPath(uuid);
|
||||||
|
newVol.setSize(srcVolume.getSize());
|
||||||
|
|
||||||
|
return new CopyCmdAnswer(newVol);
|
||||||
|
} catch (Exception e) {
|
||||||
|
String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString();
|
||||||
|
s_logger.warn(msg, e);
|
||||||
|
return new CopyCmdAnswer(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.debug("unsupported protocol");
|
||||||
|
return new CopyCmdAnswer("unsupported protocol");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Answer copyVolumeFromPrimaryToSecondary(DataTO srcData, DataTO destData, int wait) {
|
||||||
|
Connection conn = hypervisorResource.getConnection();
|
||||||
|
VolumeObjectTO srcVolume = (VolumeObjectTO)srcData;
|
||||||
|
VolumeObjectTO destVolume = (VolumeObjectTO)destData;
|
||||||
|
DataStoreTO destStore = destVolume.getDataStore();
|
||||||
|
|
||||||
|
if (destStore instanceof NfsTO) {
|
||||||
|
SR secondaryStorage = null;
|
||||||
|
try {
|
||||||
|
NfsTO nfsStore = (NfsTO)destStore;
|
||||||
|
URI uri = new URI(nfsStore.getUrl());
|
||||||
|
// Create the volume folder
|
||||||
|
if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) {
|
||||||
|
throw new InternalErrorException("Failed to create the volume folder.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a SR for the volume UUID folder
|
||||||
|
secondaryStorage = hypervisorResource.createNfsSRbyURI(conn, new URI(nfsStore.getUrl() + destVolume.getPath()), false);
|
||||||
|
// Look up the volume on the source primary storage pool
|
||||||
|
VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath());
|
||||||
|
// Copy the volume to secondary storage
|
||||||
|
VDI destVdi = hypervisorResource.cloudVDIcopy(conn, srcVdi, secondaryStorage, wait);
|
||||||
|
String destVolumeUUID = destVdi.getUuid(conn);
|
||||||
|
|
||||||
|
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||||
|
newVol.setPath(destVolumeUUID);
|
||||||
|
newVol.setSize(srcVolume.getSize());
|
||||||
|
return new CopyCmdAnswer(newVol);
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug("Failed to copy volume to secondary: " + e.toString());
|
||||||
|
return new CopyCmdAnswer("Failed to copy volume to secondary: " + e.toString());
|
||||||
|
} finally {
|
||||||
|
hypervisorResource.removeSR(conn, secondaryStorage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new CopyCmdAnswer("unsupported protocol");
|
||||||
|
}
|
||||||
|
|
||||||
protected Answer execute(CopyCommand cmd) {
|
protected Answer execute(CopyCommand cmd) {
|
||||||
DataTO srcData = cmd.getSrcTO();
|
DataTO srcData = cmd.getSrcTO();
|
||||||
DataTO destData = cmd.getDestTO();
|
DataTO destData = cmd.getDestTO();
|
||||||
@ -788,6 +859,11 @@ public class XenServerStorageResource {
|
|||||||
} else if (srcData.getObjectType() == DataObjectType.TEMPLATE && srcDataStore.getRole() == DataStoreRole.Primary && destDataStore.getRole() == DataStoreRole.Primary) {
|
} else if (srcData.getObjectType() == DataObjectType.TEMPLATE && srcDataStore.getRole() == DataStoreRole.Primary && destDataStore.getRole() == DataStoreRole.Primary) {
|
||||||
//clone template to a volume
|
//clone template to a volume
|
||||||
return cloneVolumeFromBaseTemplate(srcData, destData);
|
return cloneVolumeFromBaseTemplate(srcData, destData);
|
||||||
|
} else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.ImageCache) {
|
||||||
|
//copy volume from image cache to primary
|
||||||
|
return copyVolumeFromImageCacheToPrimary(srcData, destData, cmd.getWait());
|
||||||
|
} else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
|
||||||
|
return copyVolumeFromPrimaryToSecondary(srcData, destData, cmd.getWait());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Answer(cmd, false, "not implemented yet");
|
return new Answer(cmd, false, "not implemented yet");
|
||||||
|
|||||||
@ -101,7 +101,7 @@ public class SampleImageStoreDriverImpl implements ImageStoreDriver {
|
|||||||
if (answer.getResult()) {
|
if (answer.getResult()) {
|
||||||
//update imagestorevo
|
//update imagestorevo
|
||||||
|
|
||||||
result = new CreateCmdResult(answer.getPath(), answer.getSize());
|
result = new CreateCmdResult(answer.getPath(), null);
|
||||||
} else {
|
} else {
|
||||||
result.setResult(answer.getDetails());
|
result.setResult(answer.getDetails());
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user