GabrielBrascher commented on a change in pull request #2486: [CLOUDSTACK-10323]
Allow changing disk offering during volume migration
URL: https://github.com/apache/cloudstack/pull/2486#discussion_r184524300
##########
File path: server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
##########
@@ -2097,26 +2079,102 @@ public Volume migrateVolume(MigrateVolumeCmd cmd) {
}
}
- return orchestrateMigrateVolume(vol.getId(), destPool.getId(),
liveMigrateVolume);
+ return orchestrateMigrateVolume(vol, destPool, liveMigrateVolume,
newDiskOffering);
}
- private Volume orchestrateMigrateVolume(long volumeId, long destPoolId,
boolean liveMigrateVolume) {
- VolumeVO vol = _volsDao.findById(volumeId);
- assert (vol != null);
- StoragePool destPool =
(StoragePool)dataStoreMgr.getDataStore(destPoolId, DataStoreRole.Primary);
- assert (destPool != null);
+ /**
+ * Retrieve the new disk offering UUID that might be sent to replace the
current one in the volume being migrated.
+ * If no disk offering UUID is provided we return null. Otherwise, we
perform the following checks.
+ * <ul>
+ * <li>Is the disk offering UUID entered valid? If not, an {@link
InvalidParameterValueException} is thrown;
+ * <li>If the disk offering was already removed, we thrown an {@link
InvalidParameterValueException} is thrown;
+ * <li>We then check if the user executing the operation has access to
the given disk offering.
+ * </ul>
+ *
+ * If all checks pass, we move forward returning the disk offering object.
+ */
+ private DiskOfferingVO retrieveAndValidateNewDiskOffering(MigrateVolumeCmd
cmd) {
+ String newDiskOfferingUuid = cmd.getNewDiskOfferingUuid();
+ if (org.apache.commons.lang.StringUtils.isBlank(newDiskOfferingUuid)) {
+ return null;
+ }
+ DiskOfferingVO newDiskOffering =
_diskOfferingDao.findByUuid(newDiskOfferingUuid);
+ if (newDiskOffering == null) {
+ throw new InvalidParameterValueException(String.format("The disk
offering informed is not valid [id=%s].", newDiskOfferingUuid));
+ }
+ if (newDiskOffering.getRemoved() != null) {
+ throw new InvalidParameterValueException(String.format("We cannot
assign a removed disk offering [id=%s] to a volume. ",
newDiskOffering.getUuid()));
+ }
+ Account caller = CallContext.current().getCallingAccount();
+ _accountMgr.checkAccess(caller, newDiskOffering);
+ return newDiskOffering;
+ }
+
+ /**
+ * Performs the validations required for replacing the disk offering while
migrating the volume of storage. If no new disk offering is provided, we do not
execute any validation.
+ * If a disk offering is informed, we then proceed with the following
checks.
+ * <ul>
+ * <li>We check if the given volume is of ROOT type. We cannot change the
disk offering of a ROOT volume. Therefore, we thrown an {@link
InvalidParameterValueException}.
+ * <li>We the disk is being migrated to shared storage and the new disk
offering is for local storage (or vice versa), we throw an {@link
InvalidParameterValueException}. Bear in mind that we are validating only the
new disk offering. If none is provided we can override the current disk
offering. This means, placing a volume with shared disk offering in local
storage and vice versa.
+ * <li>We then proceed checking if the tags of the new disk offerings
match the tags of the target storage. If they do not match an {@link
InvalidParameterValueException} is thrown.
+ * </ul>
+ *
+ * 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.
+ */
+ protected void validateConditionsToReplaceDiskOfferingOfVolume(VolumeVO
volume, DiskOfferingVO newDiskOffering, StoragePool destPool) {
+ if (newDiskOffering == null) {
+ return;
+ }
+ if (Volume.Type.ROOT.equals(volume.getVolumeType())) {
+ throw new InvalidParameterValueException(String.format("Cannot
change the disk offering of a ROOT volume [id=%s].", volume.getUuid()));
+ }
+ if ((destPool.isShared() && newDiskOffering.getUseLocalStorage()) ||
destPool.isLocal() && newDiskOffering.isShared()) {
+ throw new InvalidParameterValueException("You cannot move the
volume to a shared storage and assing a disk offering for local storage and
vice versa.");
+ }
+ String storageTags = getStoragePoolTags(destPool);
+ if (!StringUtils.areTagsEqual(storageTags, newDiskOffering.getTags()))
{
+ throw new InvalidParameterValueException(String.format("Target
Storage [id=%s] tags [%s] does not match new disk offering [id=%s] tags [%s].",
destPool.getUuid(), storageTags,
+ newDiskOffering.getUuid(), newDiskOffering.getTags()));
+ }
+ if (volume.getSize() != newDiskOffering.getDiskSize()) {
+ DiskOfferingVO oldDiskOffering =
this._diskOfferingDao.findById(volume.getDiskOfferingId());
+ s_logger.warn(String.format(
+ "You are migrating a volume [id=%s] and changing the disk
offering[from id=%s to id=%s] to reflect this migration. However, the sizes of
the volume and the new disk offering are different.",
+ volume.getUuid(), oldDiskOffering.getUuid(),
newDiskOffering.getUuid()));
+ }
+ }
+
+ /**
+ * Retrieve the storage pool tags as a {@link String}. If the storage
pool does not have tags we return a null value.
Review comment:
I think that "Retrieves" would best fit here.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services