Skip to content

Commit 41acb91

Browse files
orchestration: apply custom IOPS to root volumes
Signed-off-by: xujiantop-crypto <265865031+xujiantop-crypto@users.noreply.github.com>
1 parent 6e4413d commit 41acb91

3 files changed

Lines changed: 117 additions & 5 deletions

File tree

‎api/src/main/java/com/cloud/vm/VmDetailConstants.java‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ public interface VmDetailConstants {
6666
String CPU_SPEED = "cpuSpeed";
6767
String MEMORY = "memory";
6868

69+
// VM deployment with custom root disk offering params
70+
String MIN_IOPS = "minIops";
71+
String MAX_IOPS = "maxIops";
72+
6973
// Misc details for internal usage (not to be set/changed by user or admin)
7074
String CPU_OVER_COMMIT_RATIO = "cpuOvercommitRatio";
7175
String MEMORY_OVER_COMMIT_RATIO = "memoryOvercommitRatio";

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,11 @@
5757
import com.cloud.vm.NicProfile;
5858
import com.cloud.vm.VMInstanceVO;
5959
import com.cloud.vm.VirtualMachineManager;
60+
import com.cloud.vm.VmDetailConstants;
6061
import com.cloud.vm.dao.UserVmDao;
6162
import com.cloud.vm.dao.UserVmDetailsDao;
6263
import com.cloud.vm.dao.VMInstanceDao;
6364

64-
import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS;
65-
import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS;
66-
6765
@Component
6866
public class CloudOrchestrator implements OrchestrationService {
6967

@@ -199,8 +197,8 @@ public VirtualMachineEntity createVirtualMachine(String id, String owner, String
199197
Map<String, String> userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId());
200198

201199
if (userVmDetails != null) {
202-
String minIops = userVmDetails.get(MIN_IOPS);
203-
String maxIops = userVmDetails.get(MAX_IOPS);
200+
String minIops = userVmDetails.get(VmDetailConstants.MIN_IOPS);
201+
String maxIops = userVmDetails.get(VmDetailConstants.MAX_IOPS);
204202

205203
rootDiskOfferingInfo.setMinIops(minIops != null && minIops.trim().length() > 0 ? Long.parseLong(minIops) : null);
206204
rootDiskOfferingInfo.setMaxIops(maxIops != null && maxIops.trim().length() > 0 ? Long.parseLong(maxIops) : null);
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.engine.orchestration;
18+
19+
import java.util.Collections;
20+
import java.util.HashMap;
21+
import java.util.LinkedHashMap;
22+
import java.util.Map;
23+
24+
import com.cloud.hypervisor.Hypervisor.HypervisorType;
25+
import com.cloud.offering.DiskOfferingInfo;
26+
import com.cloud.service.ServiceOfferingVO;
27+
import com.cloud.service.dao.ServiceOfferingDao;
28+
import com.cloud.storage.DiskOfferingVO;
29+
import com.cloud.storage.VMTemplateVO;
30+
import com.cloud.storage.dao.DiskOfferingDao;
31+
import com.cloud.storage.dao.VMTemplateDao;
32+
import com.cloud.utils.component.ComponentContext;
33+
import com.cloud.vm.VMInstanceVO;
34+
import com.cloud.vm.VirtualMachineManager;
35+
import com.cloud.vm.VmDetailConstants;
36+
import com.cloud.vm.dao.UserVmDetailsDao;
37+
import com.cloud.vm.dao.VMInstanceDao;
38+
import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntityImpl;
39+
import org.junit.Assert;
40+
import org.junit.Test;
41+
import org.junit.runner.RunWith;
42+
import org.mockito.ArgumentCaptor;
43+
import org.mockito.InjectMocks;
44+
import org.mockito.Mock;
45+
import org.mockito.MockedStatic;
46+
import org.mockito.Mockito;
47+
import org.mockito.junit.MockitoJUnitRunner;
48+
49+
@RunWith(MockitoJUnitRunner.class)
50+
public class CloudOrchestratorTest {
51+
52+
private static final long VM_ID = 1L;
53+
private static final long SERVICE_OFFERING_ID = 2L;
54+
private static final long ROOT_DISK_OFFERING_ID = 3L;
55+
private static final String TEMPLATE_ID = "4";
56+
57+
@InjectMocks
58+
private CloudOrchestrator cloudOrchestrator = new CloudOrchestrator();
59+
60+
@Mock
61+
private VirtualMachineManager virtualMachineManager;
62+
@Mock
63+
private VMTemplateDao templateDao;
64+
@Mock
65+
private VMInstanceDao vmDao;
66+
@Mock
67+
private UserVmDetailsDao userVmDetailsDao;
68+
@Mock
69+
private ServiceOfferingDao serviceOfferingDao;
70+
@Mock
71+
private DiskOfferingDao diskOfferingDao;
72+
73+
@Test
74+
public void createVirtualMachineSetsCustomIopsFromVmDetails() throws Exception {
75+
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
76+
ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class);
77+
DiskOfferingVO rootDiskOffering = Mockito.mock(DiskOfferingVO.class);
78+
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
79+
VirtualMachineEntityImpl vmEntity = Mockito.mock(VirtualMachineEntityImpl.class);
80+
81+
Mockito.when(vmDao.findByUuid("vm-uuid")).thenReturn(vm);
82+
Mockito.when(vm.getId()).thenReturn(VM_ID);
83+
Mockito.when(vm.getServiceOfferingId()).thenReturn(SERVICE_OFFERING_ID);
84+
Mockito.when(vm.getInstanceName()).thenReturn("i-1-1-VM");
85+
Mockito.when(serviceOfferingDao.findById(VM_ID, SERVICE_OFFERING_ID)).thenReturn(serviceOffering);
86+
Mockito.when(diskOfferingDao.findById(ROOT_DISK_OFFERING_ID)).thenReturn(rootDiskOffering);
87+
Mockito.when(rootDiskOffering.isCustomizedIops()).thenReturn(true);
88+
Mockito.when(templateDao.findById(Long.valueOf(TEMPLATE_ID))).thenReturn(template);
89+
90+
Map<String, String> details = new HashMap<>();
91+
details.put(VmDetailConstants.MIN_IOPS, "100");
92+
details.put(VmDetailConstants.MAX_IOPS, "1000");
93+
Mockito.when(userVmDetailsDao.listDetailsKeyPairs(VM_ID)).thenReturn(details);
94+
95+
try (MockedStatic<ComponentContext> componentContext = Mockito.mockStatic(ComponentContext.class)) {
96+
componentContext.when(() -> ComponentContext.inject(VirtualMachineEntityImpl.class)).thenReturn(vmEntity);
97+
98+
cloudOrchestrator.createVirtualMachine("vm-uuid", "owner", TEMPLATE_ID, "host", "display", HypervisorType.KVM.name(),
99+
1, 1000, 1024, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyMap(), null,
100+
null, null, null, null, ROOT_DISK_OFFERING_ID);
101+
}
102+
103+
ArgumentCaptor<DiskOfferingInfo> rootDiskOfferingInfo = ArgumentCaptor.forClass(DiskOfferingInfo.class);
104+
Mockito.verify(virtualMachineManager).allocate(Mockito.eq("i-1-1-VM"), Mockito.eq(template), Mockito.eq(serviceOffering), rootDiskOfferingInfo.capture(),
105+
Mockito.anyList(), Mockito.any(LinkedHashMap.class), Mockito.isNull(), Mockito.eq(HypervisorType.KVM), Mockito.isNull(), Mockito.isNull());
106+
107+
Assert.assertEquals(Long.valueOf(100), rootDiskOfferingInfo.getValue().getMinIops());
108+
Assert.assertEquals(Long.valueOf(1000), rootDiskOfferingInfo.getValue().getMaxIops());
109+
}
110+
}

0 commit comments

Comments
 (0)