Skip to content

Commit d55c4dd

Browse files
author
Mike Tutkowski
committed
CLOUDSTACK-6170
1 parent 5e4a4e8 commit d55c4dd

10 files changed

Lines changed: 172 additions & 55 deletions

File tree

api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -482,41 +482,50 @@ private void verifyDetails() {
482482
String minIops = (String)map.get("minIops");
483483
String maxIops = (String)map.get("maxIops");
484484

485-
if ((minIops != null && maxIops == null) || (minIops == null && maxIops != null)) {
486-
throw new InvalidParameterValueException("Either 'Min IOPS' and 'Max IOPS' must both be specified or neither be specified.");
487-
}
485+
verifyMinAndMaxIops(minIops, maxIops);
488486

489-
long lMinIops;
487+
minIops = (String)map.get("minIopsDo");
488+
maxIops = (String)map.get("maxIopsDo");
490489

491-
try {
492-
if (minIops != null) {
493-
lMinIops = Long.valueOf(minIops);
494-
}
495-
else {
496-
lMinIops = 0;
497-
}
490+
verifyMinAndMaxIops(minIops, maxIops);
491+
}
492+
}
493+
494+
private void verifyMinAndMaxIops(String minIops, String maxIops) {
495+
if ((minIops != null && maxIops == null) || (minIops == null && maxIops != null)) {
496+
throw new InvalidParameterValueException("Either 'Min IOPS' and 'Max IOPS' must both be specified or neither be specified.");
497+
}
498+
499+
long lMinIops;
500+
501+
try {
502+
if (minIops != null) {
503+
lMinIops = Long.valueOf(minIops);
498504
}
499-
catch (NumberFormatException ex) {
500-
throw new InvalidParameterValueException("'Min IOPS' must be a whole number.");
505+
else {
506+
lMinIops = 0;
501507
}
508+
}
509+
catch (NumberFormatException ex) {
510+
throw new InvalidParameterValueException("'Min IOPS' must be a whole number.");
511+
}
502512

503-
long lMaxIops;
513+
long lMaxIops;
504514

505-
try {
506-
if (maxIops != null) {
507-
lMaxIops = Long.valueOf(maxIops);
508-
}
509-
else {
510-
lMaxIops = 0;
511-
}
515+
try {
516+
if (maxIops != null) {
517+
lMaxIops = Long.valueOf(maxIops);
512518
}
513-
catch (NumberFormatException ex) {
514-
throw new InvalidParameterValueException("'Max IOPS' must be a whole number.");
519+
else {
520+
lMaxIops = 0;
515521
}
522+
}
523+
catch (NumberFormatException ex) {
524+
throw new InvalidParameterValueException("'Max IOPS' must be a whole number.");
525+
}
516526

517-
if (lMinIops > lMaxIops) {
518-
throw new InvalidParameterValueException("'Min IOPS' must be less than or equal to 'Max IOPS'.");
519-
}
527+
if (lMinIops > lMaxIops) {
528+
throw new InvalidParameterValueException("'Min IOPS' must be less than or equal to 'Max IOPS'.");
520529
}
521530
}
522531

engine/api/src/com/cloud/vm/VirtualMachineManager.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import com.cloud.exception.ResourceUnavailableException;
3737
import com.cloud.hypervisor.Hypervisor.HypervisorType;
3838
import com.cloud.network.Network;
39-
import com.cloud.offering.DiskOffering;
4039
import com.cloud.offering.DiskOfferingInfo;
4140
import com.cloud.offering.ServiceOffering;
4241
import com.cloud.storage.StoragePool;
@@ -77,7 +76,7 @@ public interface Topics {
7776
* @throws InsufficientCapacityException If there are insufficient capacity to deploy this vm.
7877
*/
7978
void allocate(String vmInstanceName, VirtualMachineTemplate template, ServiceOffering serviceOffering, DiskOfferingInfo rootDiskOfferingInfo,
80-
LinkedHashMap<? extends DiskOffering, Long> dataDiskOfferings, LinkedHashMap<? extends Network, List<? extends NicProfile>> auxiliaryNetworks, DeploymentPlan plan,
79+
List<DiskOfferingInfo> dataDiskOfferings, LinkedHashMap<? extends Network, List<? extends NicProfile>> auxiliaryNetworks, DeploymentPlan plan,
8180
HypervisorType hyperType) throws InsufficientCapacityException;
8281

8382
void allocate(String vmInstanceName, VirtualMachineTemplate template, ServiceOffering serviceOffering,

engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId,
8686

8787
void destroyVolume(Volume volume);
8888

89-
DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, VirtualMachine vm, VirtualMachineTemplate template, Account owner);
89+
DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner);
9090

9191
VolumeInfo createVolumeOnPrimaryStorage(VirtualMachine vm, Volume rootVolumeOfVm, VolumeInfo volume, HypervisorType rootDiskHyperType) throws NoTransitionException;
9292

engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@
154154
import com.cloud.network.dao.NetworkDao;
155155
import com.cloud.network.dao.NetworkVO;
156156
import com.cloud.network.rules.RulesManager;
157-
import com.cloud.offering.DiskOffering;
158157
import com.cloud.offering.DiskOfferingInfo;
159158
import com.cloud.offering.ServiceOffering;
160159
import com.cloud.org.Cluster;
@@ -376,7 +375,7 @@ public void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru) {
376375
@Override
377376
@DB
378377
public void allocate(String vmInstanceName, final VirtualMachineTemplate template, ServiceOffering serviceOffering,
379-
final DiskOfferingInfo rootDiskOfferingInfo, LinkedHashMap<? extends DiskOffering, Long> dataDiskOfferings,
378+
final DiskOfferingInfo rootDiskOfferingInfo, final List<DiskOfferingInfo> dataDiskOfferings,
380379
final LinkedHashMap<? extends Network, List<? extends NicProfile>> auxiliaryNetworks, DeploymentPlan plan, HypervisorType hyperType)
381380
throws InsufficientCapacityException {
382381

@@ -393,8 +392,6 @@ public void allocate(String vmInstanceName, final VirtualMachineTemplate templat
393392
}
394393
assert (plan.getClusterId() == null && plan.getPoolId() == null) : "We currently don't support cluster and pool preset yet";
395394
final VMInstanceVO vmFinal = _vmDao.persist(vm);
396-
final LinkedHashMap<? extends DiskOffering, Long> dataDiskOfferingsFinal =
397-
dataDiskOfferings == null ? new LinkedHashMap<DiskOffering, Long>() : dataDiskOfferings;
398395

399396
final VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmFinal, template, serviceOffering, null, null);
400397

@@ -416,17 +413,20 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Insuff
416413
}
417414

418415
if (template.getFormat() == ImageFormat.ISO) {
419-
volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vmFinal.getId(), rootDiskOfferingInfo.getDiskOffering(), rootDiskOfferingInfo.getSize(), vmFinal,
420-
template, owner);
416+
volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vmFinal.getId(), rootDiskOfferingInfo.getDiskOffering(), rootDiskOfferingInfo.getSize(),
417+
rootDiskOfferingInfo.getMinIops(), rootDiskOfferingInfo.getMaxIops(), vmFinal, template, owner);
421418
} else if (template.getFormat() == ImageFormat.BAREMETAL) {
422419
// Do nothing
423420
} else {
424421
volumeMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vmFinal.getId(), rootDiskOfferingInfo.getDiskOffering(), rootDiskOfferingInfo.getSize(),
425422
rootDiskOfferingInfo.getMinIops(), rootDiskOfferingInfo.getMaxIops(), template, vmFinal, owner);
426423
}
427424

428-
for (Map.Entry<? extends DiskOffering, Long> offering : dataDiskOfferingsFinal.entrySet()) {
429-
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vmFinal.getId(), offering.getKey(), offering.getValue(), vmFinal, template, owner);
425+
if (dataDiskOfferings != null) {
426+
for (DiskOfferingInfo dataDiskOfferingInfo : dataDiskOfferings) {
427+
volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vmFinal.getId(), dataDiskOfferingInfo.getDiskOffering(), dataDiskOfferingInfo.getSize(),
428+
dataDiskOfferingInfo.getMinIops(), dataDiskOfferingInfo.getMaxIops(), vmFinal, template, owner);
429+
}
430430
}
431431
}
432432
});
@@ -439,7 +439,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Insuff
439439
@Override
440440
public void allocate(String vmInstanceName, VirtualMachineTemplate template, ServiceOffering serviceOffering,
441441
LinkedHashMap<? extends Network, List<? extends NicProfile>> networks, DeploymentPlan plan, HypervisorType hyperType) throws InsufficientCapacityException {
442-
allocate(vmInstanceName, template, serviceOffering, new DiskOfferingInfo(serviceOffering), null, networks, plan, hyperType);
442+
allocate(vmInstanceName, template, serviceOffering, new DiskOfferingInfo(serviceOffering), new ArrayList<DiskOfferingInfo>(), networks, plan, hyperType);
443443
}
444444

445445
private VirtualMachineGuru getVmGuru(VirtualMachine vm) {

engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import com.cloud.network.Network;
4646
import com.cloud.network.dao.NetworkDao;
4747
import com.cloud.network.dao.NetworkVO;
48-
import com.cloud.offering.DiskOffering;
4948
import com.cloud.offering.DiskOfferingInfo;
5049
import com.cloud.service.ServiceOfferingVO;
5150
import com.cloud.service.dao.ServiceOfferingDao;
@@ -181,14 +180,14 @@ public VirtualMachineEntity createVirtualMachine(String id, String owner, String
181180
// Else, a disk offering is optional, and if present will be used to create the data disk
182181

183182
DiskOfferingInfo rootDiskOfferingInfo = new DiskOfferingInfo();
184-
LinkedHashMap<DiskOfferingVO, Long> dataDiskOfferings = new LinkedHashMap<DiskOfferingVO, Long>();
183+
List<DiskOfferingInfo> dataDiskOfferings = new ArrayList<DiskOfferingInfo>();
185184

186-
ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
185+
ServiceOfferingVO computeOffering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
187186

188-
rootDiskOfferingInfo.setDiskOffering(offering);
187+
rootDiskOfferingInfo.setDiskOffering(computeOffering);
189188
rootDiskOfferingInfo.setSize(rootDiskSize);
190189

191-
if (offering.isCustomizedIops() != null && offering.isCustomizedIops()) {
190+
if (computeOffering.isCustomizedIops() != null && computeOffering.isCustomizedIops()) {
192191
Map<String, String> userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId());
193192

194193
if (userVmDetails != null) {
@@ -213,10 +212,28 @@ public VirtualMachineEntity createVirtualMachine(String id, String owner, String
213212
}
214213
_volumeMgr.validateVolumeSizeRange(size * 1024 * 1024 * 1024);
215214
}
216-
dataDiskOfferings.put(diskOffering, size);
215+
216+
DiskOfferingInfo dataDiskOfferingInfo = new DiskOfferingInfo();
217+
218+
dataDiskOfferingInfo.setDiskOffering(diskOffering);
219+
dataDiskOfferingInfo.setSize(size);
220+
221+
if (diskOffering.isCustomizedIops() != null && diskOffering.isCustomizedIops()) {
222+
Map<String, String> userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId());
223+
224+
if (userVmDetails != null) {
225+
String minIops = userVmDetails.get("minIopsDo");
226+
String maxIops = userVmDetails.get("maxIopsDo");
227+
228+
dataDiskOfferingInfo.setMinIops(minIops != null && minIops.trim().length() > 0 ? Long.parseLong(minIops) : null);
229+
dataDiskOfferingInfo.setMaxIops(maxIops != null && maxIops.trim().length() > 0 ? Long.parseLong(maxIops) : null);
230+
}
231+
}
232+
233+
dataDiskOfferings.add(dataDiskOfferingInfo);
217234
}
218235

219-
_itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(templateId)), offering, rootDiskOfferingInfo, dataDiskOfferings, networkIpMap, plan,
236+
_itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(templateId)), computeOffering, rootDiskOfferingInfo, dataDiskOfferings, networkIpMap, plan,
220237
hypervisorType);
221238

222239
return vmEntity;
@@ -234,13 +251,12 @@ public VirtualMachineEntity createVirtualMachineFromScratch(String id, String ow
234251
//load vm instance and offerings and call virtualMachineManagerImpl
235252
VMInstanceVO vm = _vmDao.findByUuid(id);
236253

237-
ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
254+
ServiceOfferingVO computeOffering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
238255

239256
DiskOfferingInfo rootDiskOfferingInfo = new DiskOfferingInfo();
240257

241-
rootDiskOfferingInfo.setDiskOffering(offering);
258+
rootDiskOfferingInfo.setDiskOffering(computeOffering);
242259

243-
LinkedHashMap<DiskOffering, Long> dataDiskOfferings = new LinkedHashMap<DiskOffering, Long>();
244260
Long diskOfferingId = vm.getDiskOfferingId();
245261
if (diskOfferingId == null) {
246262
throw new InvalidParameterValueException("Installing from ISO requires a disk offering to be specified for the root disk.");
@@ -261,6 +277,18 @@ public VirtualMachineEntity createVirtualMachineFromScratch(String id, String ow
261277
rootDiskOfferingInfo.setDiskOffering(diskOffering);
262278
rootDiskOfferingInfo.setSize(size);
263279

280+
if (diskOffering.isCustomizedIops() != null && diskOffering.isCustomizedIops()) {
281+
Map<String, String> userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId());
282+
283+
if (userVmDetails != null) {
284+
String minIops = userVmDetails.get("minIopsDo");
285+
String maxIops = userVmDetails.get("maxIopsDo");
286+
287+
rootDiskOfferingInfo.setMinIops(minIops != null && minIops.trim().length() > 0 ? Long.parseLong(minIops) : null);
288+
rootDiskOfferingInfo.setMaxIops(maxIops != null && maxIops.trim().length() > 0 ? Long.parseLong(maxIops) : null);
289+
}
290+
}
291+
264292
LinkedHashMap<Network, List<? extends NicProfile>> networkIpMap = new LinkedHashMap<Network, List<? extends NicProfile>>();
265293
for (String uuid : networkNicMap.keySet()) {
266294
NetworkVO network = _networkDao.findByUuid(uuid);
@@ -271,7 +299,7 @@ public VirtualMachineEntity createVirtualMachineFromScratch(String id, String ow
271299

272300
HypervisorType hypervisorType = HypervisorType.valueOf(hypervisor);
273301

274-
_itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(isoId)), offering, rootDiskOfferingInfo, dataDiskOfferings, networkIpMap, plan, hypervisorType);
302+
_itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(isoId)), computeOffering, rootDiskOfferingInfo, new ArrayList<DiskOfferingInfo>(), networkIpMap, plan, hypervisorType);
275303

276304
return vmEntity;
277305
}

engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -569,14 +569,17 @@ protected DiskProfile toDiskProfile(Volume vol, DiskOffering offering) {
569569
}
570570

571571
@Override
572-
public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, VirtualMachine vm, VirtualMachineTemplate template, Account owner) {
572+
public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner) {
573573
if (size == null) {
574574
size = offering.getDiskSize();
575575
} else {
576576
size = (size * 1024 * 1024 * 1024);
577577
}
578-
VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), size, offering.getMinIops(), offering.getMaxIops(),
579-
null);
578+
579+
minIops = minIops != null ? minIops : offering.getMinIops();
580+
maxIops = maxIops != null ? maxIops : offering.getMaxIops();
581+
582+
VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), size, minIops, maxIops, null);
580583
if (vm != null) {
581584
vol.setInstanceId(vm.getId());
582585
}
@@ -1151,7 +1154,7 @@ private Pair<VolumeVO, DataStore> recreateVolume(VolumeVO vol, VirtualMachinePro
11511154

11521155
StoragePoolVO storagePool = _storagePoolDao.findById(destPool.getId());
11531156

1154-
if (newVol.getVolumeType() == Type.DATADISK && storagePool.isManaged()) {
1157+
if (storagePool.isManaged()) {
11551158
long hostId = vm.getVirtualMachine().getHostId();
11561159
Host host = _hostDao.findById(hostId);
11571160

ui/css/cloudstack3.css

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6057,6 +6057,13 @@ label.error {
60576057
border-radius: 4px;
60586058
}
60596059

6060+
.multi-wizard.instance-wizard .section.custom-iops-do {
6061+
position: relative;
6062+
background: #F4F4F4;
6063+
padding: 7px;
6064+
border-radius: 4px;
6065+
}
6066+
60606067
.multi-wizard.instance-wizard .section.custom-size input[type=radio] {
60616068
float: left;
60626069
}
@@ -6073,13 +6080,46 @@ label.error {
60736080
margin: 6px -1px 0 8px;
60746081
}
60756082

6083+
.multi-wizard.instance-wizard .section.custom-iops-do input[type=text] {
6084+
float: left;
6085+
width: 28px;
6086+
margin: 6px -1px 0 8px;
6087+
}
6088+
60766089
.multi-wizard.instance-wizard .section.custom-size label.error {
60776090
position: absolute;
60786091
top: 29px;
60796092
left: 242px;
60806093
font-size: 10px;
60816094
}
60826095

6096+
.instance-wizard .step.data-disk-offering.custom-iops-do .select-container {
6097+
height: 235px;
6098+
}
6099+
6100+
.instance-wizard .step.data-disk-offering .custom-iops-do {
6101+
display: none;
6102+
}
6103+
6104+
.instance-wizard .step.data-disk-offering.custom-iops-do .custom-iops-do {
6105+
display: block;
6106+
}
6107+
6108+
.instance-wizard .step.data-disk-offering .custom-iops-do .field {
6109+
width: 30%;
6110+
float: left;
6111+
margin-bottom: 13px;
6112+
}
6113+
6114+
.instance-wizard .step.data-disk-offering .custom-iops-do .field label {
6115+
text-indent: 20px;
6116+
}
6117+
6118+
.instance-wizard .step.data-disk-offering .custom-iops-do .field input {
6119+
width: 88%;
6120+
margin-left: 26px;
6121+
}
6122+
60836123
/*** Compute offering*/
60846124
.instance-wizard .step.service-offering {
60856125
}

ui/index.jsp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@
221221
<input type="text" class="required disallowSpecialCharacters" name="compute-memory" />
222222
</div>
223223
</div>
224-
<!-- Custom iops slider -->
224+
<!-- Custom iops -->
225225
<div class="section custom-iops">
226226
<div class="field">
227227
<label><fmt:message key="label.disk.iops.min"/></label>
@@ -259,6 +259,17 @@
259259
<input type="text" class="required digits" name="size" value="1" />
260260
<label class="size">GB</label>
261261
</div>
262+
<!-- Custom iops -->
263+
<div class="section custom-iops-do">
264+
<div class="field">
265+
<label><fmt:message key="label.disk.iops.min"/></label>
266+
<input type="text" class="disallowSpecialCharacters" name="disk-min-iops-do" />
267+
</div>
268+
<div class="field">
269+
<label><fmt:message key="label.disk.iops.max"/></label>
270+
<input type="text" class="disallowSpecialCharacters" name="disk-max-iops-do" />
271+
</div>
272+
</div>
262273
</div>
263274
</div>
264275

0 commit comments

Comments
 (0)