Skip to content

Commit 9034a8a

Browse files
committed
Refactor volume migration to remove secondary storage intermediate
1 parent 2102864 commit 9034a8a

File tree

12 files changed

+113
-1
lines changed

12 files changed

+113
-1
lines changed

core/src/main/java/com/cloud/storage/resource/StorageProcessor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,6 @@ public interface StorageProcessor {
7474
public Answer resignature(ResignatureCommand cmd);
7575

7676
public Answer handleDownloadTemplateToPrimaryStorage(DirectDownloadCommand cmd);
77+
78+
Answer copyVolumeFromPrimaryToPrimary(CopyCommand cmd);
7779
}

core/src/main/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package com.cloud.storage.resource;
2121

2222
import org.apache.cloudstack.agent.directdownload.DirectDownloadCommand;
23+
import org.apache.cloudstack.storage.to.VolumeObjectTO;
2324
import org.apache.log4j.Logger;
2425

2526
import org.apache.cloudstack.storage.command.AttachCommand;
@@ -95,7 +96,9 @@ protected Answer execute(CopyCommand cmd) {
9596
//copy volume from image cache to primary
9697
return processor.copyVolumeFromImageCacheToPrimary(cmd);
9798
} else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
98-
if (destData.getObjectType() == DataObjectType.VOLUME) {
99+
if (destData.getObjectType() == DataObjectType.VOLUME && srcData instanceof VolumeObjectTO && ((VolumeObjectTO)srcData).isDirectDownload()) {
100+
return processor.copyVolumeFromPrimaryToPrimary(cmd);
101+
} else if (destData.getObjectType() == DataObjectType.VOLUME) {
99102
return processor.copyVolumeFromPrimaryToSecondary(cmd);
100103
} else if (destData.getObjectType() == DataObjectType.TEMPLATE) {
101104
return processor.createTemplateFromVolume(cmd);

core/src/main/java/org/apache/cloudstack/storage/to/VolumeObjectTO.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public class VolumeObjectTO implements DataTO {
6161
private DiskCacheMode cacheMode;
6262
private Hypervisor.HypervisorType hypervisorType;
6363
private MigrationOptions migrationOptions;
64+
private boolean directDownload;
6465

6566
public VolumeObjectTO() {
6667

@@ -100,6 +101,7 @@ public VolumeObjectTO(VolumeInfo volume) {
100101
hypervisorType = volume.getHypervisorType();
101102
setDeviceId(volume.getDeviceId());
102103
this.migrationOptions = volume.getMigrationOptions();
104+
this.directDownload = volume.isDirectDownload();
103105
}
104106

105107
public String getUuid() {
@@ -307,4 +309,8 @@ public DiskCacheMode getCacheMode() {
307309
public MigrationOptions getMigrationOptions() {
308310
return migrationOptions;
309311
}
312+
313+
public boolean isDirectDownload() {
314+
return directDownload;
315+
}
310316
}

engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,8 @@ public interface VolumeInfo extends DataObject, Volume {
7979
MigrationOptions getMigrationOptions();
8080

8181
void setMigrationOptions(MigrationOptions migrationOptions);
82+
83+
boolean isDirectDownload();
84+
85+
void setDirectDownload(boolean directDownload);
8286
}

engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,25 @@ protected Answer copyVolumeBetweenPools(DataObject srcData, DataObject destData)
325325

326326
Scope destScope = getZoneScope(destData.getDataStore().getScope());
327327
DataStore cacheStore = cacheMgr.getCacheStorage(destScope);
328+
boolean bypassSecondaryStorage = false;
329+
if (srcData instanceof VolumeInfo && ((VolumeInfo)srcData).isDirectDownload()) {
330+
bypassSecondaryStorage = true;
331+
}
332+
328333
if (cacheStore == null) {
334+
if (bypassSecondaryStorage) {
335+
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _copyvolumewait, VirtualMachineManager.ExecuteInSequence.value());
336+
EndPoint ep = selector.select(srcData, destData);
337+
Answer answer = null;
338+
if (ep == null) {
339+
String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
340+
s_logger.error(errMsg);
341+
answer = new Answer(cmd, false, errMsg);
342+
} else {
343+
answer = ep.sendMessage(cmd);
344+
}
345+
return answer;
346+
}
329347
// need to find a nfs or cifs image store, assuming that can't copy volume
330348
// directly to s3
331349
ImageStoreEntity imageStore = (ImageStoreEntity)dataStoreMgr.getImageStoreWithFreeCapacity(destScope.getScopeId());

engine/storage/src/main/java/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ protected boolean moveBetweenPrimaryImage(DataStore srcStore, DataStore destStor
8484
}
8585
}
8686

87+
private boolean moveBetweenPrimaryDirectDownload(DataStore srcStore, DataStore destStore) {
88+
DataStoreRole srcRole = srcStore.getRole();
89+
DataStoreRole destRole = destStore.getRole();
90+
return srcRole == DataStoreRole.Primary && destRole == DataStoreRole.Primary;
91+
}
92+
8793
protected boolean moveBetweenCacheAndImage(DataStore srcStore, DataStore destStore) {
8894
DataStoreRole srcRole = srcStore.getRole();
8995
DataStoreRole destRole = destStore.getRole();
@@ -182,6 +188,8 @@ public EndPoint select(DataObject srcData, DataObject destData) {
182188
DataStore destStore = destData.getDataStore();
183189
if (moveBetweenPrimaryImage(srcStore, destStore)) {
184190
return findEndPointForImageMove(srcStore, destStore);
191+
} else if (moveBetweenPrimaryDirectDownload(srcStore, destStore)) {
192+
return findEndPointForImageMove(srcStore, destStore);
185193
} else if (moveBetweenCacheAndImage(srcStore, destStore)) {
186194
// pick ssvm based on image cache dc
187195
DataStore selectedStore = null;

engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeDataFactoryImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323

2424
import javax.inject.Inject;
2525

26+
import com.cloud.storage.VMTemplateVO;
27+
import com.cloud.storage.dao.VMTemplateDao;
2628
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
2729
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
2830
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
@@ -42,6 +44,8 @@ public class VolumeDataFactoryImpl implements VolumeDataFactory {
4244
VolumeDataStoreDao volumeStoreDao;
4345
@Inject
4446
DataStoreManager storeMgr;
47+
@Inject
48+
VMTemplateDao templateDao;
4549

4650
@Override
4751
public VolumeInfo getVolume(long volumeId, DataStore store) {
@@ -90,6 +94,12 @@ public VolumeInfo getVolume(long volumeId) {
9094
DataStore store = storeMgr.getDataStore(volumeVO.getPoolId(), DataStoreRole.Primary);
9195
vol = VolumeObject.getVolumeObject(store, volumeVO);
9296
}
97+
if (vol.getTemplateId() != null) {
98+
VMTemplateVO template = templateDao.findById(vol.getTemplateId());
99+
if (template != null) {
100+
vol.setDirectDownload(template.isDirectDownload());
101+
}
102+
}
93103
return vol;
94104
}
95105

engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeObject.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ public class VolumeObject implements VolumeInfo {
7474
DiskOfferingDao diskOfferingDao;
7575
private Object payload;
7676
private MigrationOptions migrationOptions;
77+
private boolean directDownload;
7778

7879
public VolumeObject() {
7980
_volStateMachine = Volume.State.getStateMachine();
@@ -327,6 +328,16 @@ public void setMigrationOptions(MigrationOptions migrationOptions) {
327328
this.migrationOptions = migrationOptions;
328329
}
329330

331+
@Override
332+
public boolean isDirectDownload() {
333+
return directDownload;
334+
}
335+
336+
@Override
337+
public void setDirectDownload(boolean directDownload) {
338+
this.directDownload = directDownload;
339+
}
340+
330341
public void update() {
331342
volumeDao.update(volumeVO.getId(), volumeVO);
332343
volumeVO = volumeDao.findById(volumeVO.getId());

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,6 +1742,41 @@ public Answer handleDownloadTemplateToPrimaryStorage(DirectDownloadCommand cmd)
17421742
return new DirectDownloadAnswer(true, template.getSize(), template.getName());
17431743
}
17441744

1745+
@Override
1746+
public Answer copyVolumeFromPrimaryToPrimary(CopyCommand cmd) {
1747+
final DataTO srcData = cmd.getSrcTO();
1748+
final DataTO destData = cmd.getDestTO();
1749+
final VolumeObjectTO srcVol = (VolumeObjectTO)srcData;
1750+
final VolumeObjectTO destVol = (VolumeObjectTO)destData;
1751+
final ImageFormat srcFormat = srcVol.getFormat();
1752+
final ImageFormat destFormat = destVol.getFormat();
1753+
final DataStoreTO srcStore = srcData.getDataStore();
1754+
final DataStoreTO destStore = destData.getDataStore();
1755+
final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcStore;
1756+
final PrimaryDataStoreTO primaryStoreDest = (PrimaryDataStoreTO)destStore;
1757+
final String srcVolumePath = srcData.getPath();
1758+
final String destVolumePath = destData.getPath();
1759+
KVMStoragePool destPool = null;
1760+
1761+
try {
1762+
final String volumeName = UUID.randomUUID().toString();
1763+
1764+
final String destVolumeName = volumeName + "." + destFormat.getFileExtension();
1765+
final KVMPhysicalDisk volume = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), srcVolumePath);
1766+
volume.setFormat(PhysicalDiskFormat.valueOf(srcFormat.toString()));
1767+
1768+
destPool = storagePoolMgr.getStoragePool(primaryStoreDest.getPoolType(), primaryStoreDest.getUuid());
1769+
storagePoolMgr.copyPhysicalDisk(volume, destVolumeName, destPool, cmd.getWaitInMillSeconds());
1770+
final VolumeObjectTO newVol = new VolumeObjectTO();
1771+
newVol.setPath(destVolumePath + File.separator + destVolumeName);
1772+
newVol.setFormat(destFormat);
1773+
return new CopyCmdAnswer(newVol);
1774+
} catch (final CloudRuntimeException e) {
1775+
s_logger.debug("Failed to copyVolumeFromPrimaryToPrimary: ", e);
1776+
return new CopyCmdAnswer(e.toString());
1777+
}
1778+
}
1779+
17451780
/**
17461781
* True if location exists
17471782
*/

plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3StorageProcessor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,11 @@ public Answer handleDownloadTemplateToPrimaryStorage(DirectDownloadCommand cmd)
826826
return null;
827827
}
828828

829+
@Override
830+
public Answer copyVolumeFromPrimaryToPrimary(CopyCommand cmd) {
831+
return null;
832+
}
833+
829834
/**
830835
* Attach disks
831836
* @param cmd

0 commit comments

Comments
 (0)