This is an automated email from the ASF dual-hosted git repository.

rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new 1b79466  server: allow disk offering selection for volume from 
snapshot (#3246)
1b79466 is described below

commit 1b79466dd94a12f1b14dd1e5fc51e2e54b578c67
Author: Abhishek Kumar <abhishek.ku...@shapeblue.com>
AuthorDate: Tue Jun 25 22:00:24 2019 +0530

    server: allow disk offering selection for volume from snapshot (#3246)
    
    Problem: Volume created from a snapshot does not show its disk offering.
    
    Root Cause: The volume created from a snapshot of a root disk does not have 
a disk offering therefore the disk offering of the created volume from the 
snapshot is empty.
    
    Solution: Refactored createVolume API and extended UI to allow user to 
select a disk offering while creating a volume using a root disk volume 
snapshot. For creating volumes using data disk volume snapshot, the disk 
offering given by the snapshot will be assigned. Disk offering selection in the 
UI form for volume creation from snapshot is depicted in screenshot below.
    
    Signed-off-by: Abhishek Kumar <abhishek.ku...@shapeblue.com>
---
 .../com/cloud/storage/VolumeApiServiceImpl.java    |  47 ++++---
 ui/scripts/storage.js                              | 137 ++++++++++++++++++++-
 2 files changed, 166 insertions(+), 18 deletions(-)

diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java 
b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
index 37f6d95..099f88b 100644
--- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
@@ -555,7 +555,6 @@ public class VolumeApiServiceImpl extends ManagerBase 
implements VolumeApiServic
         Long zoneId = cmd.getZoneId();
         Long diskOfferingId = null;
         DiskOfferingVO diskOffering = null;
-        Storage.ProvisioningType provisioningType;
         Long size = null;
         Long minIops = null;
         Long maxIops = null;
@@ -563,11 +562,22 @@ public class VolumeApiServiceImpl extends ManagerBase 
implements VolumeApiServic
         VolumeVO parentVolume = null;
 
         // validate input parameters before creating the volume
-        if ((cmd.getSnapshotId() == null && cmd.getDiskOfferingId() == null) 
|| (cmd.getSnapshotId() != null && cmd.getDiskOfferingId() != null)) {
-            throw new InvalidParameterValueException("Either disk Offering Id 
or snapshot Id must be passed whilst creating volume");
+        if (cmd.getSnapshotId() == null && cmd.getDiskOfferingId() == null) {
+            throw new InvalidParameterValueException("At least one of disk 
Offering ID or snapshot ID must be passed whilst creating volume");
         }
 
-        if (cmd.getSnapshotId() == null) {// create a new volume
+        // disallow passing disk offering ID with DATA disk volume snapshots
+        if (cmd.getSnapshotId() != null && cmd.getDiskOfferingId() != null) {
+            SnapshotVO snapshot = _snapshotDao.findById(cmd.getSnapshotId());
+            if (snapshot != null) {
+                parentVolume = 
_volsDao.findByIdIncludingRemoved(snapshot.getVolumeId());
+                if (parentVolume != null && parentVolume.getVolumeType() != 
Volume.Type.ROOT)
+                    throw new InvalidParameterValueException("Disk Offering ID 
cannot be passed whilst creating volume from snapshot other than ROOT disk 
snapshots");
+            }
+            parentVolume = null;
+        }
+
+        if (cmd.getDiskOfferingId() != null) { // create a new volume
 
             diskOfferingId = cmd.getDiskOfferingId();
             size = cmd.getSize();
@@ -641,13 +651,13 @@ public class VolumeApiServiceImpl extends ManagerBase 
implements VolumeApiServic
                 }
             }
 
-            provisioningType = diskOffering.getProvisioningType();
-
             if (!validateVolumeSizeRange(size)) {// convert size from mb to gb
                 // for validation
                 throw new InvalidParameterValueException("Invalid size for 
custom volume creation: " + size + " ,max volume size is:" + 
_maxVolumeSizeInGb);
             }
-        } else { // create volume from snapshot
+        }
+
+        if (cmd.getSnapshotId() != null) { // create volume from snapshot
             Long snapshotId = cmd.getSnapshotId();
             SnapshotVO snapshotCheck = _snapshotDao.findById(snapshotId);
             if (snapshotCheck == null) {
@@ -659,19 +669,25 @@ public class VolumeApiServiceImpl extends ManagerBase 
implements VolumeApiServic
             }
             parentVolume = 
_volsDao.findByIdIncludingRemoved(snapshotCheck.getVolumeId());
 
-            diskOfferingId = snapshotCheck.getDiskOfferingId();
-            diskOffering = _diskOfferingDao.findById(diskOfferingId);
             if (zoneId == null) {
                 // if zoneId is not provided, we default to create volume in 
the same zone as the snapshot zone.
                 zoneId = snapshotCheck.getDataCenterId();
             }
-            size = snapshotCheck.getSize(); // ; disk offering is used for tags
-            // purposes
 
-            minIops = snapshotCheck.getMinIops();
-            maxIops = snapshotCheck.getMaxIops();
+            if (diskOffering == null) { // Pure snapshot is being used to 
create volume.
+                diskOfferingId = snapshotCheck.getDiskOfferingId();
+                diskOffering = _diskOfferingDao.findById(diskOfferingId);
+
+                minIops = snapshotCheck.getMinIops();
+                maxIops = snapshotCheck.getMaxIops();
+                size = snapshotCheck.getSize(); // ; disk offering is used for 
tags purposes
+            } else {
+                if (size < snapshotCheck.getSize()) {
+                    throw new 
InvalidParameterValueException(String.format("Invalid size for volume creation: 
%dGB, snapshot size is: %dGB",
+                            size / (1024 * 1024 * 1024), 
snapshotCheck.getSize() / (1024 * 1024 * 1024)));
+                }
+            }
 
-            provisioningType = diskOffering.getProvisioningType();
             // check snapshot permissions
             _accountMgr.checkAccess(caller, null, true, snapshotCheck);
 
@@ -693,9 +709,10 @@ public class VolumeApiServiceImpl extends ManagerBase 
implements VolumeApiServic
                 // permission check
                 _accountMgr.checkAccess(caller, null, false, vm);
             }
-
         }
 
+        Storage.ProvisioningType provisioningType = 
diskOffering.getProvisioningType();
+
         // Check that the resource limit for primary storage won't be exceeded
         _resourceLimitMgr.checkResourceLimit(owner, 
ResourceType.primary_storage, displayVolume, new Long(size));
 
diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js
index f1d3330..789af42 100644
--- a/ui/scripts/storage.js
+++ b/ui/scripts/storage.js
@@ -1969,6 +1969,9 @@
                                         } else {
                                             
args.$form.find('.form-item[rel=zoneid]').hide();
                                         }
+                                        
if(args.context.snapshots[0].volumetype!='ROOT') {
+                                            
args.$form.find('.form-item[rel=diskOffering]').hide();
+                                        }
                                     },
                                     fields: {
                                         name: {
@@ -2005,13 +2008,110 @@
                                                     }
                                                 });
                                             }
+                                        },
+                                        diskOffering: {
+                                            label: 'label.disk.offering',
+                                            docID: 'helpVolumeDiskOffering',
+                                            select: function(args) {
+                                                var snapshotSizeInGB = 
Math.floor(args.context.snapshots[0].virtualsize/(1024 * 1024 * 1024))
+                                                $.ajax({
+                                                    url: 
createURL("listDiskOfferings"),
+                                                    dataType: "json",
+                                                    async: false,
+                                                    success: function(json) {
+                                                        diskofferingObjs = 
json.listdiskofferingsresponse.diskoffering;
+                                                        var items = [];
+                                                        // Sort offerings list 
with size and keep custom offerings at end
+                                                        for(var 
i=0;i<diskofferingObjs.length;i++) {
+                                                            for(var 
j=i+1;j<diskofferingObjs.length;j++) {
+                                                                
if((diskofferingObjs[i].disksize>diskofferingObjs[j].disksize &&
+                                                                    
diskofferingObjs[j].disksize!=0) ||
+                                                                    
(diskofferingObjs[i].disksize==0 &&
+                                                                        
diskofferingObjs[j].disksize!=0)) {
+                                                                    var temp = 
diskofferingObjs[i];
+                                                                    
diskofferingObjs[i] = diskofferingObjs[j];
+                                                                    
diskofferingObjs[j] = temp;
+                                                                }
+                                                            }
+                                                        }
+                                                        
$(diskofferingObjs).each(function() {
+                                                            
if(this.disksize==0 || this.disksize>=snapshotSizeInGB) {
+                                                                items.push({
+                                                                    id: 
this.id,
+                                                                    
description: this.displaytext
+                                                                });
+                                                            }
+                                                        });
+                                                        args.response.success({
+                                                            data: items
+                                                        });
+                                                    }
+                                                });
+
+                                                args.$select.change(function() 
{
+                                                    var diskOfferingId = 
$(this).val();
+                                                    selectedDiskOfferingObj = 
null;
+                                                    
$(diskofferingObjs).each(function() {
+                                                        if (this.id == 
diskOfferingId) {
+                                                            
selectedDiskOfferingObj = this;
+                                                            return false;
+                                                        }
+                                                    });
+
+                                                    if 
(selectedDiskOfferingObj == null) return;
+
+                                                    var $form = 
$(this).closest('form');
+                                                    var $diskSize = 
$form.find('.form-item[rel=diskSize]');
+                                                    if 
(selectedDiskOfferingObj.iscustomized == true) {
+                                                        
$diskSize.css('display', 'inline-block');
+                                                        
$form.find('input[name=diskSize]').val(''+snapshotSizeInGB);
+                                                    } else {
+                                                        $diskSize.hide();
+                                                    }
+
+                                                    var $minIops = 
$form.find('.form-item[rel=minIops]');
+                                                    var $maxIops = 
$form.find('.form-item[rel=maxIops]');
+                                                    if 
(selectedDiskOfferingObj.iscustomizediops == true) {
+                                                        
$minIops.css('display', 'inline-block');
+                                                        
$maxIops.css('display', 'inline-block');
+                                                    } else {
+                                                        $minIops.hide();
+                                                        $maxIops.hide();
+                                                    }
+                                                });
+                                            }
+                                        },
+                                        diskSize: {
+                                            label: 'label.disk.size.gb',
+                                            docID: 'helpVolumeSizeGb',
+                                            validation: {
+                                                required: true,
+                                                number: true
+                                            },
+                                            isHidden: true
+                                        },
+                                        minIops: {
+                                            label: 'label.disk.iops.min',
+                                            validation: {
+                                                required: false,
+                                                number: true
+                                            },
+                                            isHidden: true
+                                        },
+                                        maxIops: {
+                                            label: 'label.disk.iops.max',
+                                            validation: {
+                                                required: false,
+                                                number: true
+                                            },
+                                            isHidden: true
                                         }
                                     }
                                 },
                                 action: function(args) {
                                     var data = {
-                                        snapshotid: 
args.context.snapshots[0].id,
-                                        name: args.data.name
+                                        name: args.data.name,
+                                        snapshotid: 
args.context.snapshots[0].id
                                     };
 
                                     if 
(args.$form.find('.form-item[rel=zoneid]').css("display") != "none" && 
args.data.zoneid != '') {
@@ -2020,6 +2120,35 @@
                                         });
                                     }
 
+                                    if 
(args.$form.find('.form-item[rel=diskOffering]').css("display") != "none") {
+                                        if (args.data.diskOffering) {
+                                            $.extend(data, {
+                                                diskofferingid: 
args.data.diskOffering
+                                            });
+                                        }
+                                        if (selectedDiskOfferingObj) {
+                                            
if(selectedDiskOfferingObj.iscustomized == true) {
+                                                $.extend(data, {
+                                                    size: args.data.diskSize
+                                                });
+                                            }
+
+                                            if 
(selectedDiskOfferingObj.iscustomizediops == true) {
+                                                if (args.data.minIops != "" && 
args.data.minIops > 0) {
+                                                    $.extend(data, {
+                                                        miniops: 
args.data.minIops
+                                                    });
+                                                }
+
+                                                if (args.data.maxIops != "" && 
args.data.maxIops > 0) {
+                                                    $.extend(data, {
+                                                        maxiops: 
args.data.maxIops
+                                                    });
+                                                }
+                                            }
+                                        }
+                                    }
+
                                     $.ajax({
                                         url: createURL('createVolume'),
                                         data: data,
@@ -2036,6 +2165,9 @@
                                                     }
                                                 }
                                             });
+                                        },
+                                        error: function(json) {
+                                            
args.response.error(parseXMLHttpResponse(json));
                                         }
                                     });
                                 },
@@ -2043,7 +2175,6 @@
                                     poll: pollAsyncJobResult
                                 }
                             },
-
                             revertSnapshot: {
                                 label: 'label.action.revert.snapshot',
                                 messages: {

Reply via email to