in server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java [673:938]
public void updateCapacityForHost(final Host host) {
long usedCpuCore = 0;
long reservedCpuCore = 0;
long usedCpu = 0;
long usedMemory = 0;
long reservedMemory = 0;
long reservedCpu = 0;
final CapacityState capacityState = (host.getResourceState() == ResourceState.Enabled) ? CapacityState.Enabled : CapacityState.Disabled;
List<VMInstanceVO> vms = _vmDao.listIdServiceOfferingForUpVmsByHostId(host.getId());
logger.debug("Found {} VMs on {}", vms.size(), host);
final List<VMInstanceVO> vosMigrating = _vmDao.listIdServiceOfferingForVmsMigratingFromHost(host.getId());
logger.debug("Found {} VMs are Migrating from {}", vosMigrating.size(), host);
vms.addAll(vosMigrating);
Pair<String, String> clusterValues =
clusterValuesCache.get(host.getClusterId());
Float clusterCpuOvercommitRatio = Float.parseFloat(clusterValues.first());
Float clusterRamOvercommitRatio = Float.parseFloat(clusterValues.second());
for (VMInstanceVO vm : vms) {
Float cpuOvercommitRatio = 1.0f;
Float ramOvercommitRatio = 1.0f;
Map<String, String> vmDetails = getVmDetailsForCapacityCalculation(vm.getId());
String vmDetailCpu = vmDetails.get(VmDetailConstants.CPU_OVER_COMMIT_RATIO);
String vmDetailRam = vmDetails.get(VmDetailConstants.MEMORY_OVER_COMMIT_RATIO);
// if vmDetailCpu or vmDetailRam is not null it means it is running in a overcommitted cluster.
cpuOvercommitRatio = (vmDetailCpu != null) ? Float.parseFloat(vmDetailCpu) : clusterCpuOvercommitRatio;
ramOvercommitRatio = (vmDetailRam != null) ? Float.parseFloat(vmDetailRam) : clusterRamOvercommitRatio;
ServiceOffering so = getServiceOffering(vm.getServiceOfferingId());
if (so == null) {
so = _offeringsDao.findByIdIncludingRemoved(vm.getServiceOfferingId());
}
if (so.isDynamic()) {
usedMemory +=
((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.memory.name())) * 1024L * 1024L) / ramOvercommitRatio) *
clusterRamOvercommitRatio;
if(vmDetails.containsKey(UsageEventVO.DynamicParameters.cpuSpeed.name())) {
usedCpu +=
((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name())) * Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuSpeed.name()))) / cpuOvercommitRatio) *
clusterCpuOvercommitRatio;
} else {
usedCpu +=
((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name())) * so.getSpeed()) / cpuOvercommitRatio) *
clusterCpuOvercommitRatio;
}
usedCpuCore += Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name()));
} else {
usedMemory += ((so.getRamSize() * 1024L * 1024L) / ramOvercommitRatio) * clusterRamOvercommitRatio;
usedCpu += ((so.getCpu() * so.getSpeed()) / cpuOvercommitRatio) * clusterCpuOvercommitRatio;
usedCpuCore += so.getCpu();
}
}
List<VMInstanceVO> vmsByLastHostId = _vmDao.listByLastHostId(host.getId());
logger.debug("Found {} VM, not running on {}", vmsByLastHostId.size(), host);
for (VMInstanceVO vm : vmsByLastHostId) {
Float cpuOvercommitRatio = 1.0f;
Float ramOvercommitRatio = 1.0f;
long lastModificationTime = Optional.ofNullable(vm.getUpdateTime()).orElse(vm.getCreated()).getTime();
long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - lastModificationTime) / 1000;
if (secondsSinceLastUpdate < _vmCapacityReleaseInterval) {
Map<String, String> vmDetails = getVmDetailsForCapacityCalculation(vm.getId());
String vmDetailCpu = vmDetails.get(VmDetailConstants.CPU_OVER_COMMIT_RATIO);
String vmDetailRam = vmDetails.get(VmDetailConstants.MEMORY_OVER_COMMIT_RATIO);
if (vmDetailCpu != null) {
//if vmDetail_cpu is not null it means it is running in a overcommited cluster.
cpuOvercommitRatio = Float.parseFloat(vmDetailCpu);
}
if (vmDetailRam != null) {
ramOvercommitRatio = Float.parseFloat(vmDetailRam);
}
ServiceOffering so = getServiceOffering(vm.getServiceOfferingId());
if (so == null) {
so = _offeringsDao.findByIdIncludingRemoved(vm.getServiceOfferingId());
}
if (so.isDynamic()) {
reservedMemory +=
((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.memory.name())) * 1024L * 1024L) / ramOvercommitRatio) *
clusterRamOvercommitRatio;
if(vmDetails.containsKey(UsageEventVO.DynamicParameters.cpuSpeed.name())) {
reservedCpu +=
((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name())) * Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuSpeed.name()))) / cpuOvercommitRatio) *
clusterCpuOvercommitRatio;
} else {
reservedCpu +=
((Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name())) * so.getSpeed()) / cpuOvercommitRatio) *
clusterCpuOvercommitRatio;
}
reservedCpuCore += Integer.parseInt(vmDetails.get(UsageEventVO.DynamicParameters.cpuNumber.name()));
} else {
reservedMemory += ((so.getRamSize() * 1024L * 1024L) / ramOvercommitRatio) * clusterRamOvercommitRatio;
reservedCpu += (so.getCpu() * so.getSpeed() / cpuOvercommitRatio) * clusterCpuOvercommitRatio;
reservedCpuCore += so.getCpu();
}
} else {
// signal if not done already, that the VM has been stopped for skip.counting.hours,
// hence capacity will not be reserved anymore.
UserVmDetailVO messageSentFlag = _userVmDetailsDao.findDetail(vm.getId(), VmDetailConstants.MESSAGE_RESERVED_CAPACITY_FREED_FLAG);
if (messageSentFlag == null || !Boolean.valueOf(messageSentFlag.getValue())) {
_messageBus.publish(_name, "VM_ReservedCapacity_Free", PublishScope.LOCAL, vm);
if (vm.getType() == VirtualMachine.Type.User) {
UserVmVO userVM = _userVMDao.findById(vm.getId());
_userVMDao.loadDetails(userVM);
userVM.setDetail(VmDetailConstants.MESSAGE_RESERVED_CAPACITY_FREED_FLAG, "true");
_userVMDao.saveDetails(userVM);
}
}
}
}
List<CapacityVO> capacities = _capacityDao.listByHostIdTypes(host.getId(), List.of(Capacity.CAPACITY_TYPE_CPU,
Capacity.CAPACITY_TYPE_MEMORY,
CapacityVO.CAPACITY_TYPE_CPU_CORE));
CapacityVO cpuCap = null;
CapacityVO memCap = null;
CapacityVO cpuCoreCap = null;
for (CapacityVO c : capacities) {
if (c.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) {
cpuCap = c;
} else if (c.getCapacityType() == Capacity.CAPACITY_TYPE_MEMORY) {
memCap = c;
} else if (c.getCapacityType() == Capacity.CAPACITY_TYPE_CPU_CORE) {
cpuCoreCap = c;
}
if (ObjectUtils.allNotNull(cpuCap, memCap, cpuCoreCap)) {
break;
}
}
if (cpuCoreCap != null) {
long hostTotalCpuCore = host.getCpus().longValue();
if (cpuCoreCap.getTotalCapacity() != hostTotalCpuCore) {
logger.debug("Calibrate total cpu for host: {} old total CPU:{} new total CPU:{}", host, cpuCoreCap.getTotalCapacity(), hostTotalCpuCore);
cpuCoreCap.setTotalCapacity(hostTotalCpuCore);
}
if (cpuCoreCap.getUsedCapacity() == usedCpuCore && cpuCoreCap.getReservedCapacity() == reservedCpuCore) {
logger.debug("No need to calibrate cpu capacity, host:{} usedCpuCore: {} reservedCpuCore: {}", host, cpuCoreCap.getUsedCapacity(), cpuCoreCap.getReservedCapacity());
} else {
if (cpuCoreCap.getReservedCapacity() != reservedCpuCore) {
logger.debug("Calibrate reserved cpu core for host: {} old reservedCpuCore: {} new reservedCpuCore: {}", host, cpuCoreCap.getReservedCapacity(), reservedCpuCore);
cpuCoreCap.setReservedCapacity(reservedCpuCore);
}
if (cpuCoreCap.getUsedCapacity() != usedCpuCore) {
logger.debug("Calibrate used cpu core for host: {} old usedCpuCore: {} new usedCpuCore: {}", host, cpuCoreCap.getUsedCapacity(), usedCpuCore);
cpuCoreCap.setUsedCapacity(usedCpuCore);
}
}
try {
_capacityDao.update(cpuCoreCap.getId(), cpuCoreCap);
} catch (Exception e) {
logger.error("Caught exception while updating cpucore capacity for the host {}", host, e);
}
} else {
final long usedCpuCoreFinal = usedCpuCore;
final long reservedCpuCoreFinal = reservedCpuCore;
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
CapacityVO capacity = new CapacityVO(host.getId(), host.getDataCenterId(), host.getPodId(), host.getClusterId(), usedCpuCoreFinal, host.getCpus().longValue(),
CapacityVO.CAPACITY_TYPE_CPU_CORE);
capacity.setReservedCapacity(reservedCpuCoreFinal);
capacity.setCapacityState(capacityState);
_capacityDao.persist(capacity);
}
});
}
if (cpuCap != null && memCap != null) {
if (host.getTotalMemory() != null) {
memCap.setTotalCapacity(host.getTotalMemory());
}
long hostTotalCpu = host.getCpus().longValue() * host.getSpeed().longValue();
if (cpuCap.getTotalCapacity() != hostTotalCpu) {
logger.debug("Calibrate total cpu for host: {} old total CPU:{} new total CPU:{}", host, cpuCap.getTotalCapacity(), hostTotalCpu);
cpuCap.setTotalCapacity(hostTotalCpu);
}
// Set the capacity state as per the host allocation state.
if(capacityState != cpuCap.getCapacityState()){
logger.debug("Calibrate cpu capacity state for host: {} old capacity state:{} new capacity state:{}", host, cpuCap.getTotalCapacity(), hostTotalCpu);
cpuCap.setCapacityState(capacityState);
}
memCap.setCapacityState(capacityState);
if (cpuCap.getUsedCapacity() == usedCpu && cpuCap.getReservedCapacity() == reservedCpu) {
logger.debug("No need to calibrate cpu capacity, host:{} usedCpu: {} reservedCpu: {}", host, cpuCap.getUsedCapacity(), cpuCap.getReservedCapacity());
} else {
if (cpuCap.getReservedCapacity() != reservedCpu) {
logger.debug("Calibrate reserved cpu for host: {} old reservedCpu:{} new reservedCpu:{}", host, cpuCap.getReservedCapacity(), reservedCpu);
cpuCap.setReservedCapacity(reservedCpu);
}
if (cpuCap.getUsedCapacity() != usedCpu) {
logger.debug("Calibrate used cpu for host: {} old usedCpu:{} new usedCpu:{}", host, cpuCap.getUsedCapacity(), usedCpu);
cpuCap.setUsedCapacity(usedCpu);
}
}
if (memCap.getTotalCapacity() != host.getTotalMemory()) {
logger.debug("Calibrate total memory for host: {} old total memory:{} new total memory:{}", host, toHumanReadableSize(memCap.getTotalCapacity()), toHumanReadableSize(host.getTotalMemory()));
memCap.setTotalCapacity(host.getTotalMemory());
}
// Set the capacity state as per the host allocation state.
if(capacityState != memCap.getCapacityState()){
logger.debug("Calibrate memory capacity state for host: {} old capacity state:{} new capacity state:{}", host, memCap.getTotalCapacity(), hostTotalCpu);
memCap.setCapacityState(capacityState);
}
if (memCap.getUsedCapacity() == usedMemory && memCap.getReservedCapacity() == reservedMemory) {
logger.debug("No need to calibrate memory capacity, host:{} usedMem: {} reservedMem: {}", host, toHumanReadableSize(memCap.getUsedCapacity()), toHumanReadableSize(memCap.getReservedCapacity()));
} else {
if (memCap.getReservedCapacity() != reservedMemory) {
logger.debug("Calibrate reserved memory for host: {} old reservedMem:{} new reservedMem:{}", host, memCap.getReservedCapacity(), reservedMemory);
memCap.setReservedCapacity(reservedMemory);
}
if (memCap.getUsedCapacity() != usedMemory) {
/*
* Didn't calibrate for used memory, because VMs can be in
* state(starting/migrating) that I don't know on which host
* they are allocated
*/
logger.debug("Calibrate used memory for host: {} old usedMem: {} new usedMem: {}", host, toHumanReadableSize(memCap.getUsedCapacity()), toHumanReadableSize(usedMemory));
memCap.setUsedCapacity(usedMemory);
}
}
try {
_capacityDao.update(cpuCap.getId(), cpuCap);
_capacityDao.update(memCap.getId(), memCap);
} catch (Exception e) {
logger.error("Caught exception while updating cpu/memory capacity for the host {}", host, e);
}
} else {
final long usedMemoryFinal = usedMemory;
final long reservedMemoryFinal = reservedMemory;
final long usedCpuFinal = usedCpu;
final long reservedCpuFinal = reservedCpu;
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
CapacityVO capacity =
new CapacityVO(host.getId(), host.getDataCenterId(), host.getPodId(), host.getClusterId(), usedMemoryFinal, host.getTotalMemory(),
Capacity.CAPACITY_TYPE_MEMORY);
capacity.setReservedCapacity(reservedMemoryFinal);
capacity.setCapacityState(capacityState);
_capacityDao.persist(capacity);
capacity =
new CapacityVO(host.getId(), host.getDataCenterId(), host.getPodId(), host.getClusterId(), usedCpuFinal, host.getCpus().longValue() *
host.getSpeed().longValue(), Capacity.CAPACITY_TYPE_CPU);
capacity.setReservedCapacity(reservedCpuFinal);
capacity.setCapacityState(capacityState);
_capacityDao.persist(capacity);
}
});
}
}