Skip to content

Commit 1a03c3f

Browse files
Update suitable disk offering(s) for volume(s) after migrate VM with volumes when change in pool type (shared or local)
Currently, Migrate VM with volume(s) bypasses the service and disk offerings of the volumes, as the target pools for migration are specified, which ignores the offerings. Offering change is required when pool type (shared or local) is changed, mainly - when volume on shared pool is migrated to local pool - when volume on local pool is migrated to shared pool
1 parent b134782 commit 1a03c3f

File tree

7 files changed

+57
-7
lines changed

7 files changed

+57
-7
lines changed

api/src/main/java/com/cloud/offering/DiskOffering.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public String toString() {
6969

7070
boolean isCustomized();
7171

72+
boolean isShared();
73+
7274
void setDiskSize(long diskSize);
7375

7476
long getDiskSize();
@@ -99,7 +101,6 @@ public String toString() {
99101

100102
Long getBytesReadRateMaxLength();
101103

102-
103104
void setBytesWriteRate(Long bytesWriteRate);
104105

105106
Long getBytesWriteRate();
@@ -112,7 +113,6 @@ public String toString() {
112113

113114
Long getBytesWriteRateMaxLength();
114115

115-
116116
void setIopsReadRate(Long iopsReadRate);
117117

118118
Long getIopsReadRate();
@@ -133,7 +133,6 @@ public String toString() {
133133

134134
Long getIopsWriteRateMax();
135135

136-
137136
void setIopsWriteRateMaxLength(Long iopsWriteRateMaxLength);
138137

139138
Long getIopsWriteRateMaxLength();

api/src/main/java/com/cloud/storage/VolumeApiService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ Volume updateVolume(long volumeId, String path, String state, Long storageId,
180180
*/
181181
boolean doesStoragePoolSupportDiskOfferingTags(StoragePool destPool, String diskOfferingTags);
182182

183+
boolean validateConditionsToReplaceDiskOfferingOfVolume(Volume volume, DiskOffering newDiskOffering, StoragePool destPool);
184+
183185
Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge);
184186

185187
void destroyVolume(long volumeId);

engine/schema/src/main/java/com/cloud/storage/DiskOfferingVO.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,11 +577,11 @@ public Integer getHypervisorSnapshotReserve() {
577577
@Override
578578
public void setEncrypt(boolean encrypt) { this.encrypt = encrypt; }
579579

580+
@Override
580581
public boolean isShared() {
581582
return !useLocalStorage;
582583
}
583584

584-
585585
public boolean getDiskSizeStrictness() {
586586
return diskSizeStrictness;
587587
}

engine/schema/src/main/java/com/cloud/storage/dao/DiskOfferingDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public interface DiskOfferingDao extends GenericDao<DiskOfferingVO, Long> {
3131
List<DiskOfferingVO> listAllBySizeAndProvisioningType(long size, Storage.ProvisioningType provisioningType);
3232

3333
List<DiskOfferingVO> findCustomDiskOfferings();
34+
3435
List<DiskOfferingVO> listByStorageTag(String tag);
3536

37+
List<DiskOfferingVO> listAllActiveAndNonComputeDiskOfferings();
3638
}

engine/schema/src/main/java/com/cloud/storage/dao/DiskOfferingDaoImpl.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import javax.inject.Inject;
2727
import javax.persistence.EntityExistsException;
2828

29+
import com.cloud.offering.DiskOffering;
2930
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
3031
import org.springframework.stereotype.Component;
3132

@@ -45,6 +46,8 @@ public class DiskOfferingDaoImpl extends GenericDaoBase<DiskOfferingVO, Long> im
4546
protected DiskOfferingDetailsDao detailsDao;
4647

4748
protected final SearchBuilder<DiskOfferingVO> UniqueNameSearch;
49+
protected final SearchBuilder<DiskOfferingVO> ActiveAndNonComputeSearch;
50+
4851
private final String SizeDiskOfferingSearch = "SELECT * FROM disk_offering WHERE " +
4952
"disk_size = ? AND provisioning_type = ? AND removed IS NULL";
5053

@@ -56,6 +59,11 @@ protected DiskOfferingDaoImpl() {
5659
UniqueNameSearch.and("name", UniqueNameSearch.entity().getUniqueName(), SearchCriteria.Op.EQ);
5760
UniqueNameSearch.done();
5861

62+
ActiveAndNonComputeSearch = createSearchBuilder();
63+
ActiveAndNonComputeSearch.and("state", ActiveAndNonComputeSearch.entity().getState(), SearchCriteria.Op.EQ);
64+
ActiveAndNonComputeSearch.and("computeOnly", ActiveAndNonComputeSearch.entity().isComputeOnly(), SearchCriteria.Op.EQ);
65+
ActiveAndNonComputeSearch.done();
66+
5967
_computeOnlyAttr = _allAttributes.get("computeOnly");
6068
}
6169

@@ -164,4 +172,12 @@ public List<DiskOfferingVO> listByStorageTag(String tag) {
164172
sc.setParameters("tagEndLike", "%," + tag);
165173
return listBy(sc);
166174
}
175+
176+
@Override
177+
public List<DiskOfferingVO> listAllActiveAndNonComputeDiskOfferings() {
178+
SearchCriteria<DiskOfferingVO> sc = ActiveAndNonComputeSearch.create();
179+
sc.setParameters("state", DiskOffering.State.Active);
180+
sc.setParameters("computeOnly", false);
181+
return listBy(sc);
182+
}
167183
}

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

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
import com.cloud.storage.VMTemplateStorageResourceAssoc;
123123
import com.cloud.storage.VMTemplateVO;
124124
import com.cloud.storage.Volume;
125+
import com.cloud.storage.VolumeApiService;
125126
import com.cloud.storage.VolumeDetailVO;
126127
import com.cloud.storage.VolumeVO;
127128
import com.cloud.storage.dao.DiskOfferingDao;
@@ -194,6 +195,8 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
194195
@Inject
195196
private VolumeService _volumeService;
196197
@Inject
198+
public VolumeApiService _volumeApiService;
199+
@Inject
197200
private StorageCacheManager cacheMgr;
198201
@Inject
199202
private EndPointSelector selector;
@@ -2349,11 +2352,22 @@ private void handlePostMigration(boolean success, Map<VolumeInfo, VolumeInfo> sr
23492352
volumeVO.setFormat(ImageFormat.QCOW2);
23502353
volumeVO.setLastId(srcVolumeInfo.getId());
23512354

2355+
if (Objects.equals(srcVolumeInfo.getDiskOfferingId(), destVolumeInfo.getDiskOfferingId())) {
2356+
StoragePoolVO srcPoolVO = _storagePoolDao.findById(srcVolumeInfo.getPoolId());
2357+
StoragePoolVO destPoolVO = _storagePoolDao.findById(destVolumeInfo.getPoolId());
2358+
if (srcPoolVO != null && destPoolVO != null &&
2359+
((srcPoolVO.isShared() && destPoolVO.isLocal()) || (srcPoolVO.isLocal() && destPoolVO.isShared()))) {
2360+
Long offeringId = getSuitableDiskOfferingForVolumeOnPool(volumeVO, destPoolVO);
2361+
if (offeringId != null) {
2362+
volumeVO.setDiskOfferingId(offeringId);
2363+
}
2364+
}
2365+
}
2366+
23522367
_volumeDao.update(volumeVO.getId(), volumeVO);
23532368

23542369
_volumeService.copyPoliciesBetweenVolumesAndDestroySourceVolumeAfterMigration(Event.OperationSuccessed, null, srcVolumeInfo, destVolumeInfo, false);
23552370

2356-
23572371
// Update the volume ID for snapshots on secondary storage
23582372
if (!_snapshotDao.listByVolumeId(srcVolumeInfo.getId()).isEmpty()) {
23592373
_snapshotDao.updateVolumeIds(srcVolumeInfo.getId(), destVolumeInfo.getId());
@@ -2395,6 +2409,21 @@ private void handlePostMigration(boolean success, Map<VolumeInfo, VolumeInfo> sr
23952409
}
23962410
}
23972411

2412+
private Long getSuitableDiskOfferingForVolumeOnPool(VolumeVO volume, StoragePoolVO pool) {
2413+
List<DiskOfferingVO> diskOfferings = _diskOfferingDao.listAllActiveAndNonComputeDiskOfferings();
2414+
for (DiskOfferingVO diskOffering : diskOfferings) {
2415+
try {
2416+
if (_volumeApiService.validateConditionsToReplaceDiskOfferingOfVolume(volume, diskOffering, pool)) {
2417+
logger.debug("Found suitable disk offering {} for the volume {}", diskOffering, volume);
2418+
return diskOffering.getId();
2419+
}
2420+
} catch (Exception ignore) {
2421+
}
2422+
}
2423+
logger.warn("Unable to find suitable disk offering for the volume {}", volume);
2424+
return null;
2425+
}
2426+
23982427
private VolumeVO duplicateVolumeOnAnotherStorage(Volume volume, StoragePoolVO storagePoolVO) {
23992428
Long lastPoolId = volume.getPoolId();
24002429

server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3648,9 +3648,10 @@ private DiskOfferingVO retrieveAndValidateNewDiskOffering(MigrateVolumeCmd cmd)
36483648
*
36493649
* If all of the above validations pass, we check if the size of the new disk offering is different from the volume. If it is, we log a warning message.
36503650
*/
3651-
protected void validateConditionsToReplaceDiskOfferingOfVolume(VolumeVO volume, DiskOfferingVO newDiskOffering, StoragePool destPool) {
3651+
@Override
3652+
public boolean validateConditionsToReplaceDiskOfferingOfVolume(Volume volume, DiskOffering newDiskOffering, StoragePool destPool) {
36523653
if (newDiskOffering == null) {
3653-
return;
3654+
return false;
36543655
}
36553656
if ((destPool.isShared() && newDiskOffering.isUseLocalStorage()) || destPool.isLocal() && newDiskOffering.isShared()) {
36563657
throw new InvalidParameterValueException("You cannot move the volume to a shared storage and assign a disk offering for local storage and vice versa.");
@@ -3678,6 +3679,7 @@ protected void validateConditionsToReplaceDiskOfferingOfVolume(VolumeVO volume,
36783679
volume, oldDiskOffering, newDiskOffering);
36793680
}
36803681
logger.info("Changing disk offering to [{}] while migrating volume [{}].", newDiskOffering, volume);
3682+
return true;
36813683
}
36823684

36833685
/**

0 commit comments

Comments
 (0)