From 3906dadb8a4d8fc8ffe19f110f876b51dd0ff349 Mon Sep 17 00:00:00 2001 From: Anurag Awasthi Date: Fri, 25 Jan 2019 16:10:23 +0530 Subject: [PATCH 1/5] server: allow disk offering selection for volume from snapshot Snapshots created for ROOT disk does not have disk offering id therefore when volume is created from them resulting volume also doesn't have any disk offering. This change allows selection of disk offering in UI when creating volumes from such snapshots. Signed-off-by: Abhishek Kumar --- .../cloud/storage/VolumeApiServiceImpl.java | 42 ++++-- ui/scripts/storage.js | 136 +++++++++++++++++- 2 files changed, 160 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 23b56e98da38..c0f6e0125cb9 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -556,7 +556,6 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept Long zoneId = cmd.getZoneId(); Long diskOfferingId = null; DiskOfferingVO diskOffering = null; - Storage.ProvisioningType provisioningType; Long size = null; Long minIops = null; Long maxIops = null; @@ -564,11 +563,22 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept 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(); @@ -642,13 +652,13 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept } } - 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) { @@ -660,19 +670,20 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept } 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 + } - provisioningType = diskOffering.getProvisioningType(); // check snapshot permissions _accountMgr.checkAccess(caller, null, true, snapshotCheck); @@ -694,9 +705,10 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept // 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 06fe41e2f712..cb7f93944dcd 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,21 +2008,146 @@ } }); } + }, + 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;idiskofferingObjs[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.data.diskOffering) { + $.extend(data, { + diskofferingid: args.data.diskOffering + }); + } + if (args.$form.find('.form-item[rel=zoneid]').css("display") != "none" && args.data.zoneid != '') { $.extend(data, { zoneId: args.data.zoneid }); } + 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 +2164,9 @@ } } }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); } }); }, @@ -2043,7 +2174,6 @@ poll: pollAsyncJobResult } }, - revertSnapshot: { label: 'label.action.revert.snapshot', messages: { From bf4e50bec675a9974231c6114039092535a55bbc Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 13 Jun 2019 15:17:26 +0530 Subject: [PATCH 2/5] ui: fix for extra diskofferingid param for data disk snaps to volume Signed-off-by: Abhishek Kumar --- ui/scripts/storage.js | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js index cb7f93944dcd..485942e26646 100644 --- a/ui/scripts/storage.js +++ b/ui/scripts/storage.js @@ -2114,36 +2114,37 @@ snapshotid: args.context.snapshots[0].id }; - if (args.data.diskOffering) { - $.extend(data, { - diskofferingid: args.data.diskOffering - }); - } - if (args.$form.find('.form-item[rel=zoneid]').css("display") != "none" && args.data.zoneid != '') { $.extend(data, { zoneId: args.data.zoneid }); } - if (selectedDiskOfferingObj) { - if(selectedDiskOfferingObj.iscustomized == true) { + if (args.$form.find('.form-item[rel=diskOffering]').css("display") != "none") { + if (args.data.diskOffering) { $.extend(data, { - size: args.data.diskSize + diskofferingid: args.data.diskOffering }); } - - if (selectedDiskOfferingObj.iscustomizediops == true) { - if (args.data.minIops != "" && args.data.minIops > 0) { + if (selectedDiskOfferingObj) { + if(selectedDiskOfferingObj.iscustomized == true) { $.extend(data, { - miniops: args.data.minIops + size: args.data.diskSize }); } - if (args.data.maxIops != "" && args.data.maxIops > 0) { - $.extend(data, { - maxiops: args.data.maxIops - }); + 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 + }); + } } } } From 53d006b68e7393a2fe370995a6cbcce3a5dfbd4a Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 20 Jun 2019 16:41:50 +0530 Subject: [PATCH 3/5] ui: fix for allowing volume creation without offering Signed-off-by: Abhishek Kumar --- ui/scripts/storage.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js index 485942e26646..c7672de4facc 100644 --- a/ui/scripts/storage.js +++ b/ui/scripts/storage.js @@ -2042,6 +2042,10 @@ }); } }); + items.unshift({ + id: undefined, + description: "" + }); args.response.success({ data: items }); From 89483444013eab8a580a0b8bcfabdcd07ad8683d Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 21 Jun 2019 01:29:49 +0530 Subject: [PATCH 4/5] server: added disk offering size check for volume creation from snapshot Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/storage/VolumeApiServiceImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index c0f6e0125cb9..596df4d2c361 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -682,6 +682,11 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept 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))); + } } // check snapshot permissions From b76e6c58796db03f16790756caef67d131b95d46 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 21 Jun 2019 16:08:10 +0530 Subject: [PATCH 5/5] ui: revert 53d006b Signed-off-by: Abhishek Kumar --- ui/scripts/storage.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js index c7672de4facc..485942e26646 100644 --- a/ui/scripts/storage.js +++ b/ui/scripts/storage.js @@ -2042,10 +2042,6 @@ }); } }); - items.unshift({ - id: undefined, - description: "" - }); args.response.success({ data: items });