sureshanaparti commented on a change in pull request #5008:
URL: https://github.com/apache/cloudstack/pull/5008#discussion_r698999668



##########
File path: ui/public/locales/en.json
##########
@@ -1414,6 +1419,7 @@
 "label.migrate.to.host": "Migrate to host",
 "label.migrate.to.storage": "Migrate to storage",
 "label.migrate.volume": "Migrate Volume",
+"message.migrate.volume.tooltip": "Volume can be migrated to any suitable 
storagepool. Admin has to choose the appropriate disk offering to replace, that 
supports the new storage pool",

Review comment:
       ```suggestion
   "message.migrate.volume.tooltip": "Volume can be migrated to any suitable 
storage pool. Admin has to choose the appropriate disk offering to replace, 
that supports the new storage pool",
   ```

##########
File path: ui/public/locales/en.json
##########
@@ -844,6 +846,9 @@
 "label.duration.in.sec": "Duration (in sec)",
 "label.dynamicscalingenabled": "Dynamic Scaling Enabled",
 "label.dynamicscalingenabled.tooltip": "VM can dynamically scale only when 
dynamic scaling is enabled on template, service offering and global setting",
+"label.diskofferingstrictness": "Disk Offering Strictness",
+"label.disksizestrictness": "Disk Size Strictness",
+"label.iscomputeonly.offering": "Compute only Disk Offering",

Review comment:
       ```suggestion
   "label.computeonly.offering": "Compute only Disk Offering",
   ```

##########
File path: 
api/src/main/java/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java
##########
@@ -74,6 +75,15 @@ public boolean isLiveMigrate() {
         return (liveMigrate != null) ? liveMigrate : false;
     }
 
+    public MigrateVolumeCmd() {
+
+    }

Review comment:
       ```suggestion
       }
       
   ```

##########
File path: 
api/src/main/java/org/apache/cloudstack/api/response/ServiceOfferingResponse.java
##########
@@ -486,4 +504,35 @@ public Boolean getDynamicScalingEnabled() {
     public void setDynamicScalingEnabled(Boolean dynamicScalingEnabled) {
         this.dynamicScalingEnabled = dynamicScalingEnabled;
     }
+
+    public Boolean getDiskOfferingStrictness() {
+        return diskOfferingStrictness;
+    }
+
+    public void setDiskOfferingStrictness(Boolean diskOfferingStrictness) {
+        this.diskOfferingStrictness = diskOfferingStrictness;
+    }

Review comment:
       ```suggestion
       }
       
   ```

##########
File path: 
plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java
##########
@@ -453,8 +453,14 @@ private Long 
getImportingVMGuestOs(VirtualMachineConfigSummary configSummary) {
      */
     private ServiceOfferingVO createServiceOfferingForVMImporting(Integer 
cpus, Integer memory, Integer maxCpuUsage) {
         String name = "Imported-" + cpus + "-" + memory;
-        ServiceOfferingVO vo = new ServiceOfferingVO(name, cpus, memory, 
maxCpuUsage, null, null, false, name, Storage.ProvisioningType.THIN, false, 
false, null, false, Type.User,
+
+        DiskOfferingVO diskOfferingVO = new DiskOfferingVO(name, name, 
Storage.ProvisioningType.THIN, false, null, false, false, true);
+        diskOfferingVO = 
diskOfferingDao.persistDefaultDiskOffering(diskOfferingVO);
+

Review comment:
       double white spaces

##########
File path: 
server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
##########
@@ -2501,14 +2501,23 @@ public ServiceOffering createServiceOffering(final 
CreateServiceOfferingCmd cmd)
             }
         }
 
+        // Check that the the disk offering is specified

Review comment:
       ```suggestion
           // Check that the disk offering is specified
   ```

##########
File path: 
server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
##########
@@ -2501,14 +2501,23 @@ public ServiceOffering createServiceOffering(final 
CreateServiceOfferingCmd cmd)
             }
         }
 
+        // Check that the the disk offering is specified

Review comment:
       ```suggestion
           // Check that the disk offering is specified
   ```
   
   can remove this comment, as it is evident from code ?

##########
File path: 
server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
##########
@@ -2501,14 +2501,23 @@ public ServiceOffering createServiceOffering(final 
CreateServiceOfferingCmd cmd)
             }
         }
 
+        // Check that the the disk offering is specified
+        final Long diskOfferingId = cmd.getDiskOfferingId();
+        if (diskOfferingId != null) {
+            DiskOfferingVO diskOffering = 
_diskOfferingDao.findById(diskOfferingId);
+            if ((diskOffering == null) || diskOffering.getRemoved() != null || 
diskOffering.isComputeOnly()) {

Review comment:
       `diskOffering.getRemoved()` is null all time, may not be required in the 
cond.

##########
File path: 
server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java
##########
@@ -1448,10 +1452,15 @@ public int compare(Volume v1, Volume v2) {
                                 else
                                     requestVolumes = new ArrayList<Volume>();
                                 requestVolumes.add(vol);
-
+                                List<Pair<Volume, DiskProfile>> 
volumeDiskProfilePair = new ArrayList<>();
+                                for (Volume volume: requestVolumes) {
+                                    DiskOfferingVO diskOffering = 
_diskOfferingDao.findById(volume.getDiskOfferingId());
+                                    DiskProfile diskProfile = new 
DiskProfile(volume, diskOffering, _volsDao.getHypervisorType(volume.getId()));
+                                    volumeDiskProfilePair.add(new 
Pair<>(volume, diskProfile));

Review comment:
       possible to move creation of volume disk profile pair (from the 
volumes), to a common method and use it across?

##########
File path: server/src/main/java/com/cloud/server/ManagementServerImpl.java
##########
@@ -3453,6 +3491,7 @@ public long getMemoryOrCpuCapacityByHost(final Long 
hostId, final short capacity
         cmdList.add(IssueOutOfBandManagementPowerActionCmd.class);
         cmdList.add(ChangeOutOfBandManagementPasswordCmd.class);
         cmdList.add(GetUserKeysCmd.class);
+        cmdList.add(ChangeOfferingForVolumeCmd.class);

Review comment:
       Better to move this to the volume cmds added above.
   
   
https://github.com/apache/cloudstack/blob/3ddcf858767ff5f79986457cbbac4c856b73e0bd/server/src/main/java/com/cloud/server/ManagementServerImpl.java#L3260-L3271
   
   

##########
File path: server/src/main/java/com/cloud/storage/StorageManagerImpl.java
##########
@@ -2317,13 +2322,13 @@ public boolean storagePoolHasEnoughIops(List<Volume> 
requestedVolumes, StoragePo
     }
 
     @Override
-    public boolean storagePoolHasEnoughSpace(List<Volume> volumes, StoragePool 
pool) {
-        return storagePoolHasEnoughSpace(volumes, pool, null);
+    public boolean storagePoolHasEnoughSpace(List<Pair<Volume, DiskProfile>> 
volumeDiskProfilePairs, StoragePool pool) {
+        return storagePoolHasEnoughSpace(volumeDiskProfilePairs, pool, null);
     }
 
     @Override
-    public boolean storagePoolHasEnoughSpace(List<Volume> volumes, StoragePool 
pool, Long clusterId) {
-        if (volumes == null || volumes.isEmpty()) {
+    public boolean storagePoolHasEnoughSpace(List<Pair<Volume, DiskProfile>> 
volumeDiskProfilesList, StoragePool pool, Long clusterId) {
+        if (volumeDiskProfilesList == null || 
volumeDiskProfilesList.isEmpty()) {

Review comment:
       ```suggestion
           if (CollectionUtils.isEmpty(volumeDiskProfilesList)) {
   ```

##########
File path: server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
##########
@@ -1596,6 +1622,341 @@ public Volume recoverVolume(long volumeId) {
         return volume;
     }
 
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_VOLUME_CHANGE_DISK_OFFERING, 
eventDescription = "Changing disk offering of a volume")
+    public Volume changeDiskOfferingForVolume(ChangeOfferingForVolumeCmd cmd) 
throws ResourceAllocationException {
+        Long newSize = cmd.getSize();
+        Long newMinIops = cmd.getMinIops();
+        Long newMaxIops = cmd.getMaxIops();
+        Integer newHypervisorSnapshotReserve = null;
+        boolean autoMigrateVolume = cmd.getAutoMigrate();
+
+        boolean volumeMigrateRequired = false;
+        boolean volumeResizeRequired = false;
+
+        VolumeVO volume = _volsDao.findById(cmd.getId());
+        if (volume == null) {
+            throw new InvalidParameterValueException("No such volume");
+        }
+        long currentSize = volume.getSize();
+
+        DiskOfferingVO diskOffering = 
_diskOfferingDao.findById(volume.getDiskOfferingId());
+        DiskOfferingVO newDiskOffering = 
_diskOfferingDao.findById(cmd.getNewDiskOfferingId());
+
+        /* Does the caller have authority to act on this volume? */
+        _accountMgr.checkAccess(CallContext.current().getCallingAccount(), 
null, true, volume);
+
+        // VALIDATIONS
+
+        if (newDiskOffering.getId() == diskOffering.getId()) {
+            throw new InvalidParameterValueException(String.format("Volume %s 
already have the new disk offering %s provided", volume.getUuid(), 
diskOffering.getUuid()));
+        }
+
+        Long updateNewSize[] = {newSize};
+        Long updateNewMinIops[] = {newMinIops};
+        Long updateNewMaxIops[] = {newMaxIops};
+        Integer updateNewHypervisorSnapshotReserve[] = 
{newHypervisorSnapshotReserve};
+        validateVolumeResizeWithNewDiskOfferingAndLoad(volume, diskOffering, 
newDiskOffering, updateNewSize, updateNewMinIops, updateNewMaxIops, 
updateNewHypervisorSnapshotReserve);
+        newSize = updateNewSize[0];
+        newMinIops = updateNewMinIops[0];
+        newMaxIops = updateNewMaxIops[0];
+        newHypervisorSnapshotReserve = updateNewHypervisorSnapshotReserve[0];
+        validateVolumeResizeWithSize(volume, currentSize, newSize, true);
+
+        /* If this volume has never been beyond allocated state, short circuit 
everything and simply update the database. */
+        // We need to publish this event to usage_volume table
+        if (volume.getState() == Volume.State.Allocated) {
+            s_logger.debug("Volume is in the allocated state, but has never 
been created. Simply updating database with new size and IOPS.");

Review comment:
       Better to keep volume id / name in the log here 

##########
File path: server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
##########
@@ -1596,6 +1622,341 @@ public Volume recoverVolume(long volumeId) {
         return volume;
     }
 
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_VOLUME_CHANGE_DISK_OFFERING, 
eventDescription = "Changing disk offering of a volume")
+    public Volume changeDiskOfferingForVolume(ChangeOfferingForVolumeCmd cmd) 
throws ResourceAllocationException {
+        Long newSize = cmd.getSize();
+        Long newMinIops = cmd.getMinIops();
+        Long newMaxIops = cmd.getMaxIops();
+        Integer newHypervisorSnapshotReserve = null;
+        boolean autoMigrateVolume = cmd.getAutoMigrate();
+
+        boolean volumeMigrateRequired = false;
+        boolean volumeResizeRequired = false;
+
+        VolumeVO volume = _volsDao.findById(cmd.getId());
+        if (volume == null) {
+            throw new InvalidParameterValueException("No such volume");
+        }
+        long currentSize = volume.getSize();
+
+        DiskOfferingVO diskOffering = 
_diskOfferingDao.findById(volume.getDiskOfferingId());
+        DiskOfferingVO newDiskOffering = 
_diskOfferingDao.findById(cmd.getNewDiskOfferingId());
+
+        /* Does the caller have authority to act on this volume? */
+        _accountMgr.checkAccess(CallContext.current().getCallingAccount(), 
null, true, volume);
+
+        // VALIDATIONS
+
+        if (newDiskOffering.getId() == diskOffering.getId()) {
+            throw new InvalidParameterValueException(String.format("Volume %s 
already have the new disk offering %s provided", volume.getUuid(), 
diskOffering.getUuid()));
+        }
+
+        Long updateNewSize[] = {newSize};
+        Long updateNewMinIops[] = {newMinIops};
+        Long updateNewMaxIops[] = {newMaxIops};
+        Integer updateNewHypervisorSnapshotReserve[] = 
{newHypervisorSnapshotReserve};
+        validateVolumeResizeWithNewDiskOfferingAndLoad(volume, diskOffering, 
newDiskOffering, updateNewSize, updateNewMinIops, updateNewMaxIops, 
updateNewHypervisorSnapshotReserve);
+        newSize = updateNewSize[0];
+        newMinIops = updateNewMinIops[0];
+        newMaxIops = updateNewMaxIops[0];
+        newHypervisorSnapshotReserve = updateNewHypervisorSnapshotReserve[0];
+        validateVolumeResizeWithSize(volume, currentSize, newSize, true);
+
+        /* If this volume has never been beyond allocated state, short circuit 
everything and simply update the database. */
+        // We need to publish this event to usage_volume table
+        if (volume.getState() == Volume.State.Allocated) {
+            s_logger.debug("Volume is in the allocated state, but has never 
been created. Simply updating database with new size and IOPS.");
+
+            volume.setSize(newSize);
+            volume.setMinIops(newMinIops);
+            volume.setMaxIops(newMaxIops);
+            volume.setHypervisorSnapshotReserve(newHypervisorSnapshotReserve);
+
+            if (newDiskOffering != null) {
+                volume.setDiskOfferingId(cmd.getNewDiskOfferingId());
+            }
+
+            _volsDao.update(volume.getId(), volume);
+            if (currentSize != newSize) {
+                
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_RESIZE, 
volume.getAccountId(), volume.getDataCenterId(), volume.getId(), 
volume.getName(),
+                        volume.getDiskOfferingId(), volume.getTemplateId(), 
volume.getSize(), Volume.class.getName(), volume.getUuid());
+            }
+            return volume;
+        }
+
+        if 
(MatchStoragePoolTagsWithDiskOffering.valueIn(volume.getDataCenterId())) {
+            if (!doesNewDiskOfferingHasTagsAsOldDiskOffering(diskOffering, 
newDiskOffering)) {
+                throw new 
InvalidParameterValueException(String.format("Selected disk offering %s does 
not have tags as in existing disk offering of volume", diskOffering.getUuid(), 
volume.getUuid()));

Review comment:
       ```suggestion
                   throw new 
InvalidParameterValueException(String.format("Selected disk offering %s does 
not have tags as in existing disk offering of volume %s", 
diskOffering.getUuid(), volume.getUuid()));
   ```

##########
File path: server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
##########
@@ -1596,6 +1622,341 @@ public Volume recoverVolume(long volumeId) {
         return volume;
     }
 
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_VOLUME_CHANGE_DISK_OFFERING, 
eventDescription = "Changing disk offering of a volume")
+    public Volume changeDiskOfferingForVolume(ChangeOfferingForVolumeCmd cmd) 
throws ResourceAllocationException {
+        Long newSize = cmd.getSize();
+        Long newMinIops = cmd.getMinIops();
+        Long newMaxIops = cmd.getMaxIops();
+        Integer newHypervisorSnapshotReserve = null;
+        boolean autoMigrateVolume = cmd.getAutoMigrate();
+
+        boolean volumeMigrateRequired = false;
+        boolean volumeResizeRequired = false;
+
+        VolumeVO volume = _volsDao.findById(cmd.getId());
+        if (volume == null) {
+            throw new InvalidParameterValueException("No such volume");
+        }
+        long currentSize = volume.getSize();
+
+        DiskOfferingVO diskOffering = 
_diskOfferingDao.findById(volume.getDiskOfferingId());
+        DiskOfferingVO newDiskOffering = 
_diskOfferingDao.findById(cmd.getNewDiskOfferingId());
+
+        /* Does the caller have authority to act on this volume? */
+        _accountMgr.checkAccess(CallContext.current().getCallingAccount(), 
null, true, volume);
+
+        // VALIDATIONS
+
+        if (newDiskOffering.getId() == diskOffering.getId()) {
+            throw new InvalidParameterValueException(String.format("Volume %s 
already have the new disk offering %s provided", volume.getUuid(), 
diskOffering.getUuid()));
+        }
+
+        Long updateNewSize[] = {newSize};
+        Long updateNewMinIops[] = {newMinIops};
+        Long updateNewMaxIops[] = {newMaxIops};
+        Integer updateNewHypervisorSnapshotReserve[] = 
{newHypervisorSnapshotReserve};
+        validateVolumeResizeWithNewDiskOfferingAndLoad(volume, diskOffering, 
newDiskOffering, updateNewSize, updateNewMinIops, updateNewMaxIops, 
updateNewHypervisorSnapshotReserve);
+        newSize = updateNewSize[0];
+        newMinIops = updateNewMinIops[0];
+        newMaxIops = updateNewMaxIops[0];
+        newHypervisorSnapshotReserve = updateNewHypervisorSnapshotReserve[0];
+        validateVolumeResizeWithSize(volume, currentSize, newSize, true);
+
+        /* If this volume has never been beyond allocated state, short circuit 
everything and simply update the database. */
+        // We need to publish this event to usage_volume table
+        if (volume.getState() == Volume.State.Allocated) {
+            s_logger.debug("Volume is in the allocated state, but has never 
been created. Simply updating database with new size and IOPS.");
+
+            volume.setSize(newSize);
+            volume.setMinIops(newMinIops);
+            volume.setMaxIops(newMaxIops);
+            volume.setHypervisorSnapshotReserve(newHypervisorSnapshotReserve);
+
+            if (newDiskOffering != null) {
+                volume.setDiskOfferingId(cmd.getNewDiskOfferingId());
+            }
+
+            _volsDao.update(volume.getId(), volume);
+            if (currentSize != newSize) {
+                
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_RESIZE, 
volume.getAccountId(), volume.getDataCenterId(), volume.getId(), 
volume.getName(),
+                        volume.getDiskOfferingId(), volume.getTemplateId(), 
volume.getSize(), Volume.class.getName(), volume.getUuid());
+            }
+            return volume;
+        }
+
+        if 
(MatchStoragePoolTagsWithDiskOffering.valueIn(volume.getDataCenterId())) {
+            if (!doesNewDiskOfferingHasTagsAsOldDiskOffering(diskOffering, 
newDiskOffering)) {
+                throw new 
InvalidParameterValueException(String.format("Selected disk offering %s does 
not have tags as in existing disk offering of volume", diskOffering.getUuid(), 
volume.getUuid()));
+            }
+        }
+
+        if (currentSize != newSize || newMaxIops != volume.getMaxIops() || 
newMinIops != volume.getMinIops()) {
+            volumeResizeRequired = true;
+            validateVolumeResizeChecks(volume, currentSize, newSize);
+        }
+
+        StoragePoolVO existingStoragePool = 
_storagePoolDao.findById(volume.getPoolId());
+
+        Pair<List<? extends StoragePool>, List<? extends StoragePool>> 
poolsPair = 
managementService.listStoragePoolsForMigrationOfVolumeInternal(volume.getId(), 
newDiskOffering.getId(), newSize, newMinIops, newMaxIops, true);
+        List<? extends StoragePool> suitableStoragePools = poolsPair.second();
+
+        if (!suitableStoragePools.stream().anyMatch(p -> (p.getId() == 
existingStoragePool.getId()))) {
+            volumeMigrateRequired = true;
+            if (!autoMigrateVolume) {
+                throw new InvalidParameterValueException("Failed to change 
offering for volume since automigrate is set to false but volume needs to 
migrated");

Review comment:
       Keep volume id / name in the log here

##########
File path: server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
##########
@@ -5367,12 +5414,17 @@ public UserVm createVirtualMachine(DeployVMCmd cmd) 
throws InsufficientCapacityE
         }
 
         Long serviceOfferingId = cmd.getServiceOfferingId();
+        Long overrideDiskOfferingId = cmd.getOverrideDiskOfferingId();
 
         ServiceOffering serviceOffering = 
_entityMgr.findById(ServiceOffering.class, serviceOfferingId);
         if (serviceOffering == null) {
             throw new InvalidParameterValueException("Unable to find service 
offering: " + serviceOfferingId);
         }
 
+        if (serviceOffering.getDiskOfferingStrictness() && 
overrideDiskOfferingId != null) {
+            throw new InvalidParameterValueException(String.format("Cannot 
user override disk offering id %d since provided service offering is strictly 
mapped to its disk offering", overrideDiskOfferingId));

Review comment:
       ```suggestion
               throw new InvalidParameterValueException(String.format("Cannot 
override disk offering id %d since provided service offering is strictly mapped 
to its disk offering", overrideDiskOfferingId));
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to