public void updateCapacityForHost()

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);
                }
            });

        }

    }