Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.log4j.Logger;

import com.cloud.agent.AgentManager;
Expand Down Expand Up @@ -65,12 +66,16 @@
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.UserVmDetailVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachineProfileImpl;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;

public class RollingMaintenanceManagerImpl extends ManagerBase implements RollingMaintenanceManager {
Expand All @@ -86,6 +91,8 @@ public class RollingMaintenanceManagerImpl extends ManagerBase implements Rollin
@Inject
private VMInstanceDao vmInstanceDao;
@Inject
protected UserVmDetailsDao userVmDetailsDao;
@Inject
private ServiceOfferingDao serviceOfferingDao;
@Inject
private ClusterDetailsDao clusterDetailsDao;
Expand Down Expand Up @@ -621,10 +628,19 @@ private Pair<Boolean, String> performCapacityChecksBeforeHostInMaintenance(Host
int successfullyCheckedVmMigrations = 0;
for (VMInstanceVO runningVM : vmsRunning) {
boolean canMigrateVm = false;
Ternary<Integer, Integer, Integer> cpuSpeedAndRamSize = getComputeResourcesCpuSpeedAndRamSize(runningVM);
Integer cpu = cpuSpeedAndRamSize.first();
Integer speed = cpuSpeedAndRamSize.second();
Integer ramSize = cpuSpeedAndRamSize.third();
if (ObjectUtils.anyNull(cpu, speed,ramSize)) {
s_logger.warn(String.format("Cannot fetch compute resources for the VM %s, skipping it from the capacity check", runningVM));
continue;
}

ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(runningVM.getServiceOfferingId());
for (Host hostInCluster : hostsInCluster) {
if (!checkHostTags(hostTags, hostTagsDao.getHostTags(hostInCluster.getId()), serviceOffering.getHostTag())) {
s_logger.debug(String.format("Host tags mismatch between %s and %s Skipping it from the capacity check", host, hostInCluster));
s_logger.warn(String.format("Host tags mismatch between %s and %s, skipping it from the capacity check", host, hostInCluster));
continue;
}
DeployDestination deployDestination = new DeployDestination(null, null, null, host);
Expand All @@ -634,13 +650,13 @@ private Pair<Boolean, String> performCapacityChecksBeforeHostInMaintenance(Host
affinityChecks = affinityChecks && affinityProcessor.check(vmProfile, deployDestination);
}
if (!affinityChecks) {
s_logger.debug(String.format("Affinity check failed between %s and %s Skipping it from the capacity check", host, hostInCluster));
s_logger.warn(String.format("Affinity check failed between %s and %s, skipping it from the capacity check", host, hostInCluster));
continue;
}
boolean maxGuestLimit = capacityManager.checkIfHostReachMaxGuestLimit(host);
boolean hostHasCPUCapacity = capacityManager.checkIfHostHasCpuCapability(hostInCluster.getId(), serviceOffering.getCpu(), serviceOffering.getSpeed());
int cpuRequested = serviceOffering.getCpu() * serviceOffering.getSpeed();
long ramRequested = serviceOffering.getRamSize() * 1024L * 1024L;
boolean hostHasCPUCapacity = capacityManager.checkIfHostHasCpuCapability(hostInCluster.getId(), cpu, speed);
int cpuRequested = cpu * speed;
long ramRequested = ramSize * 1024L * 1024L;
ClusterDetailsVO clusterDetailsCpuOvercommit = clusterDetailsDao.findDetail(cluster.getId(), "cpuOvercommitRatio");
ClusterDetailsVO clusterDetailsRamOvercommmt = clusterDetailsDao.findDetail(cluster.getId(), "memoryOvercommitRatio");
Float cpuOvercommitRatio = Float.parseFloat(clusterDetailsCpuOvercommit.getValue());
Expand All @@ -666,11 +682,42 @@ private Pair<Boolean, String> performCapacityChecksBeforeHostInMaintenance(Host
return new Pair<>(true, "OK");
}

protected Ternary<Integer, Integer, Integer> getComputeResourcesCpuSpeedAndRamSize(VMInstanceVO runningVM) {
ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(runningVM.getServiceOfferingId());
Integer cpu = serviceOffering.getCpu();
Integer speed = serviceOffering.getSpeed();
Integer ramSize = serviceOffering.getRamSize();
if (!serviceOffering.isDynamic()) {
return new Ternary<>(cpu, speed, ramSize);
}

List<UserVmDetailVO> vmDetails = userVmDetailsDao.listDetails(runningVM.getId());
if (CollectionUtils.isEmpty(vmDetails)) {
return new Ternary<>(cpu, speed, ramSize);
}

for (UserVmDetailVO vmDetail : vmDetails) {
if (StringUtils.isBlank(vmDetail.getName()) || StringUtils.isBlank(vmDetail.getValue())) {
continue;
}

if (cpu == null && VmDetailConstants.CPU_NUMBER.equals(vmDetail.getName())) {
cpu = Integer.valueOf(vmDetail.getValue());
} else if (speed == null && VmDetailConstants.CPU_SPEED.equals(vmDetail.getName())) {
speed = Integer.valueOf(vmDetail.getValue());
} else if (ramSize == null && VmDetailConstants.MEMORY.equals(vmDetail.getName())) {
ramSize = Integer.valueOf(vmDetail.getValue());
}
}

return new Ternary<>(cpu, speed, ramSize);
}

/**
* Check hosts tags
*/
private boolean checkHostTags(List<HostTagVO> hostTags, List<HostTagVO> hostInClusterTags, String offeringTag) {
if (CollectionUtils.isEmpty(hostTags) && CollectionUtils.isEmpty(hostInClusterTags)) {
if ((CollectionUtils.isEmpty(hostTags) && CollectionUtils.isEmpty(hostInClusterTags)) || StringUtils.isBlank(offeringTag)) {
return true;
} else if ((CollectionUtils.isNotEmpty(hostTags) && CollectionUtils.isEmpty(hostInClusterTags)) ||
(CollectionUtils.isEmpty(hostTags) && CollectionUtils.isNotEmpty(hostInClusterTags))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,15 @@
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.org.Cluster;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.utils.Ternary;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.UserVmDetailVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.dao.UserVmDetailsDao;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -53,6 +61,12 @@ public class RollingMaintenanceManagerImplTest {
HostVO host4;
@Mock
Cluster cluster;
@Mock
VMInstanceVO vm;
@Mock
ServiceOfferingDao serviceOfferingDao;
@Mock
UserVmDetailsDao userVmDetailsDao;

@Spy
@InjectMocks
Expand Down Expand Up @@ -164,4 +178,50 @@ public void testPerformStateChecksForce() {

Assert.assertEquals(1, hosts.size());
}

@Test
public void testGetComputeResourcesCpuSpeedAndRamSize_ForNormalOffering() {
ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class);
Mockito.when(serviceOffering.isDynamic()).thenReturn(false);
Mockito.when(serviceOffering.getCpu()).thenReturn(1);
Mockito.when(serviceOffering.getSpeed()).thenReturn(500);
Mockito.when(serviceOffering.getRamSize()).thenReturn(512);

Mockito.when(vm.getServiceOfferingId()).thenReturn(1L);
Mockito.when(serviceOfferingDao.findById(1L)).thenReturn(serviceOffering);

Ternary<Integer, Integer, Integer> cpuSpeedAndRamSize = manager.getComputeResourcesCpuSpeedAndRamSize(vm);

Assert.assertEquals(1, cpuSpeedAndRamSize.first().intValue());
Assert.assertEquals(500, cpuSpeedAndRamSize.second().intValue());
Assert.assertEquals(512, cpuSpeedAndRamSize.third().intValue());
}

@Test
public void testGetComputeResourcesCpuSpeedAndRamSize_ForCustomOffering() {
ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class);
Mockito.when(serviceOffering.isDynamic()).thenReturn(true);
Mockito.when(serviceOffering.getCpu()).thenReturn(null);
Mockito.when(serviceOffering.getSpeed()).thenReturn(null);
Mockito.when(serviceOffering.getRamSize()).thenReturn(null);

List<UserVmDetailVO> vmDetails = new ArrayList<>();
UserVmDetailVO cpuDetail = new UserVmDetailVO(1L, VmDetailConstants.CPU_NUMBER, "2", false);
vmDetails.add(cpuDetail);
UserVmDetailVO speedDetail = new UserVmDetailVO(1L, VmDetailConstants.CPU_SPEED, "1000", false);
vmDetails.add(speedDetail);
UserVmDetailVO ramSizeDetail = new UserVmDetailVO(1L, VmDetailConstants.MEMORY, "1024", false);
vmDetails.add(ramSizeDetail);

Mockito.when(vm.getId()).thenReturn(1L);
Mockito.when(vm.getServiceOfferingId()).thenReturn(1L);
Mockito.when(serviceOfferingDao.findById(1L)).thenReturn(serviceOffering);
Mockito.when(userVmDetailsDao.listDetails(1L)).thenReturn(vmDetails);

Ternary<Integer, Integer, Integer> cpuSpeedAndRamSize = manager.getComputeResourcesCpuSpeedAndRamSize(vm);

Assert.assertEquals(2, cpuSpeedAndRamSize.first().intValue());
Assert.assertEquals(1000, cpuSpeedAndRamSize.second().intValue());
Assert.assertEquals(1024, cpuSpeedAndRamSize.third().intValue());
}
}
Loading