@DB @Override public void updateCapacityForHost(HostVO host) { // prepare the service offerings List<ServiceOfferingVO> offerings = _offeringsDao.listAllIncludingRemoved(); Map<Long, ServiceOfferingVO> offeringsMap = new HashMap<Long, ServiceOfferingVO>(); for (ServiceOfferingVO offering : offerings) { offeringsMap.put(offering.getId(), offering); } long usedCpu = 0; long usedMemory = 0; long reservedMemory = 0; long reservedCpu = 0; List<VMInstanceVO> vms = _vmDao.listUpByHostId(host.getId()); if (s_logger.isDebugEnabled()) { s_logger.debug("Found " + vms.size() + " VMs on host " + host.getId()); } for (VMInstanceVO vm : vms) { ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId()); usedMemory += so.getRamSize() * 1024L * 1024L; usedCpu += so.getCpu() * so.getSpeed(); } List<VMInstanceVO> vmsByLastHostId = _vmDao.listByLastHostId(host.getId()); if (s_logger.isDebugEnabled()) { s_logger.debug( "Found " + vmsByLastHostId.size() + " VM, not running on host " + host.getId()); } for (VMInstanceVO vm : vmsByLastHostId) { long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - vm.getUpdateTime().getTime()) / 1000; if (secondsSinceLastUpdate < _vmCapacityReleaseInterval) { ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId()); reservedMemory += so.getRamSize() * 1024L * 1024L; reservedCpu += so.getCpu() * so.getSpeed(); } } CapacityVO cpuCap = _capacityDao.findByHostIdType(host.getId(), CapacityVO.CAPACITY_TYPE_CPU); CapacityVO memCap = _capacityDao.findByHostIdType(host.getId(), CapacityVO.CAPACITY_TYPE_MEMORY); if (cpuCap != null && memCap != null) { if (cpuCap.getUsedCapacity() == usedCpu && cpuCap.getReservedCapacity() == reservedCpu) { s_logger.debug( "No need to calibrate cpu capacity, host:" + host.getId() + " usedCpu: " + cpuCap.getUsedCapacity() + " reservedCpu: " + cpuCap.getReservedCapacity()); } else if (cpuCap.getReservedCapacity() != reservedCpu) { s_logger.debug( "Calibrate reserved cpu for host: " + host.getId() + " old reservedCpu:" + cpuCap.getReservedCapacity() + " new reservedCpu:" + reservedCpu); cpuCap.setReservedCapacity(reservedCpu); } else if (cpuCap.getUsedCapacity() != usedCpu) { s_logger.debug( "Calibrate used cpu for host: " + host.getId() + " old usedCpu:" + cpuCap.getUsedCapacity() + " new usedCpu:" + usedCpu); cpuCap.setUsedCapacity(usedCpu); } if (memCap.getUsedCapacity() == usedMemory && memCap.getReservedCapacity() == reservedMemory) { s_logger.debug( "No need to calibrate memory capacity, host:" + host.getId() + " usedMem: " + memCap.getUsedCapacity() + " reservedMem: " + memCap.getReservedCapacity()); } else if (memCap.getReservedCapacity() != reservedMemory) { s_logger.debug( "Calibrate reserved memory for host: " + host.getId() + " old reservedMem:" + memCap.getReservedCapacity() + " new reservedMem:" + reservedMemory); memCap.setReservedCapacity(reservedMemory); } else 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 */ s_logger.debug( "Calibrate used memory for host: " + host.getId() + " old usedMem: " + memCap.getUsedCapacity() + " new usedMem: " + usedMemory); memCap.setUsedCapacity(usedMemory); } try { _capacityDao.update(cpuCap.getId(), cpuCap); _capacityDao.update(memCap.getId(), memCap); } catch (Exception e) { s_logger.error( "Caught exception while updating cpu/memory capacity for the host " + host.getId(), e); } } else { Transaction txn = Transaction.currentTxn(); CapacityState capacityState = _configMgr.findClusterAllocationState(ApiDBUtils.findClusterById(host.getClusterId())) == AllocationState.Disabled ? CapacityState.Disabled : CapacityState.Enabled; txn.start(); CapacityVO capacity = new CapacityVO( host.getId(), host.getDataCenterId(), host.getPodId(), host.getClusterId(), usedMemory, host.getTotalMemory(), CapacityVO.CAPACITY_TYPE_MEMORY); capacity.setReservedCapacity(reservedMemory); capacity.setCapacityState(capacityState); _capacityDao.persist(capacity); capacity = new CapacityVO( host.getId(), host.getDataCenterId(), host.getPodId(), host.getClusterId(), usedCpu, (long) (host.getCpus().longValue() * host.getSpeed().longValue()), CapacityVO.CAPACITY_TYPE_CPU); capacity.setReservedCapacity(reservedCpu); capacity.setCapacityState(capacityState); _capacityDao.persist(capacity); txn.commit(); } }
@DB @Override public void allocateVmCapacity(VirtualMachine vm, boolean fromLastHost) { long hostId = vm.getHostId(); HostVO host = _hostDao.findById(hostId); long clusterId = host.getClusterId(); float cpuOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio").getValue()); float memoryOvercommitRatio = Float.parseFloat( _clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio").getValue()); ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId()); CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU); CapacityVO capacityMem = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY); if (capacityCpu == null || capacityMem == null || svo == null) { return; } int cpu = (int) (svo.getCpu() * svo.getSpeed()); long ram = (long) (svo.getRamSize() * 1024L * 1024L); Transaction txn = Transaction.currentTxn(); try { txn.start(); capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true); capacityMem = _capacityDao.lockRow(capacityMem.getId(), true); long usedCpu = capacityCpu.getUsedCapacity(); long usedMem = capacityMem.getUsedCapacity(); long reservedCpu = capacityCpu.getReservedCapacity(); long reservedMem = capacityMem.getReservedCapacity(); long actualTotalCpu = capacityCpu.getTotalCapacity(); long actualTotalMem = capacityMem.getTotalCapacity(); long totalCpu = (long) (actualTotalCpu * cpuOvercommitRatio); long totalMem = (long) (actualTotalMem * memoryOvercommitRatio); if (s_logger.isDebugEnabled()) { s_logger.debug( "Hosts's actual total CPU: " + actualTotalCpu + " and CPU after applying overprovisioning: " + totalCpu); } long freeCpu = totalCpu - (reservedCpu + usedCpu); long freeMem = totalMem - (reservedMem + usedMem); if (s_logger.isDebugEnabled()) { s_logger.debug("We are allocating VM, increasing the used capacity of this host:" + hostId); s_logger.debug( "Current Used CPU: " + usedCpu + " , Free CPU:" + freeCpu + " ,Requested CPU: " + cpu); s_logger.debug( "Current Used RAM: " + usedMem + " , Free RAM:" + freeMem + " ,Requested RAM: " + ram); } capacityCpu.setUsedCapacity(usedCpu + cpu); capacityMem.setUsedCapacity(usedMem + ram); if (fromLastHost) { /* alloc from reserved */ if (s_logger.isDebugEnabled()) { s_logger.debug( "We are allocating VM to the last host again, so adjusting the reserved capacity if it is not less than required"); s_logger.debug("Reserved CPU: " + reservedCpu + " , Requested CPU: " + cpu); s_logger.debug("Reserved RAM: " + reservedMem + " , Requested RAM: " + ram); } if (reservedCpu >= cpu && reservedMem >= ram) { capacityCpu.setReservedCapacity(reservedCpu - cpu); capacityMem.setReservedCapacity(reservedMem - ram); } } else { /* alloc from free resource */ if (!((reservedCpu + usedCpu + cpu <= totalCpu) && (reservedMem + usedMem + ram <= totalMem))) { if (s_logger.isDebugEnabled()) { s_logger.debug( "Host doesnt seem to have enough free capacity, but increasing the used capacity anyways, since the VM is already starting on this host "); } } } s_logger.debug( "CPU STATS after allocation: for host: " + hostId + ", old used: " + usedCpu + ", old reserved: " + reservedCpu + ", actual total: " + actualTotalCpu + ", total with overprovisioning: " + totalCpu + "; new used:" + capacityCpu.getUsedCapacity() + ", reserved:" + capacityCpu.getReservedCapacity() + "; requested cpu:" + cpu + ",alloc_from_last:" + fromLastHost); s_logger.debug( "RAM STATS after allocation: for host: " + hostId + ", old used: " + usedMem + ", old reserved: " + reservedMem + ", total: " + totalMem + "; new used: " + capacityMem.getUsedCapacity() + ", reserved: " + capacityMem.getReservedCapacity() + "; requested mem: " + ram + ",alloc_from_last:" + fromLastHost); _capacityDao.update(capacityCpu.getId(), capacityCpu); _capacityDao.update(capacityMem.getId(), capacityMem); txn.commit(); } catch (Exception e) { txn.rollback(); return; } }
@Override public boolean checkIfHostHasCapacity( long hostId, Integer cpu, long ram, boolean checkFromReservedCapacity, float cpuOvercommitRatio, float memoryOvercommitRatio, boolean considerReservedCapacity) { boolean hasCapacity = false; if (s_logger.isDebugEnabled()) { s_logger.debug( "Checking if host: " + hostId + " has enough capacity for requested CPU: " + cpu + " and requested RAM: " + ram + " , cpuOverprovisioningFactor: " + cpuOvercommitRatio); } CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU); CapacityVO capacityMem = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY); if (capacityCpu == null || capacityMem == null) { if (capacityCpu == null) { if (s_logger.isDebugEnabled()) { s_logger.debug( "Cannot checkIfHostHasCapacity, Capacity entry for CPU not found in Db, for hostId: " + hostId); } } if (capacityMem == null) { if (s_logger.isDebugEnabled()) { s_logger.debug( "Cannot checkIfHostHasCapacity, Capacity entry for RAM not found in Db, for hostId: " + hostId); } } return false; } long usedCpu = capacityCpu.getUsedCapacity(); long usedMem = capacityMem.getUsedCapacity(); long reservedCpu = capacityCpu.getReservedCapacity(); long reservedMem = capacityMem.getReservedCapacity(); long actualTotalCpu = capacityCpu.getTotalCapacity(); long actualTotalMem = capacityMem.getTotalCapacity(); long totalCpu = (long) (actualTotalCpu * cpuOvercommitRatio); long totalMem = (long) (actualTotalMem * memoryOvercommitRatio); if (s_logger.isDebugEnabled()) { s_logger.debug( "Hosts's actual total CPU: " + actualTotalCpu + " and CPU after applying overprovisioning: " + totalCpu); } String failureReason = ""; if (checkFromReservedCapacity) { long freeCpu = reservedCpu; long freeMem = reservedMem; if (s_logger.isDebugEnabled()) { s_logger.debug( "We need to allocate to the last host again, so checking if there is enough reserved capacity"); s_logger.debug("Reserved CPU: " + freeCpu + " , Requested CPU: " + cpu); s_logger.debug("Reserved RAM: " + freeMem + " , Requested RAM: " + ram); } /* alloc from reserved */ if (reservedCpu >= cpu) { if (reservedMem >= ram) { hasCapacity = true; } else { failureReason = "Host does not have enough reserved RAM available"; } } else { failureReason = "Host does not have enough reserved CPU available"; } } else { long reservedCpuValueToUse = reservedCpu; long reservedMemValueToUse = reservedMem; if (!considerReservedCapacity) { if (s_logger.isDebugEnabled()) { s_logger.debug( "considerReservedCapacity is" + considerReservedCapacity + " , not considering reserved capacity for calculating free capacity"); } reservedCpuValueToUse = 0; reservedMemValueToUse = 0; } long freeCpu = totalCpu - (reservedCpuValueToUse + usedCpu); long freeMem = totalMem - (reservedMemValueToUse + usedMem); if (s_logger.isDebugEnabled()) { s_logger.debug("Free CPU: " + freeCpu + " , Requested CPU: " + cpu); s_logger.debug("Free RAM: " + freeMem + " , Requested RAM: " + ram); } /* alloc from free resource */ if ((reservedCpuValueToUse + usedCpu + cpu <= totalCpu)) { if ((reservedMemValueToUse + usedMem + ram <= totalMem)) { hasCapacity = true; } else { failureReason = "Host does not have enough RAM available"; } } else { failureReason = "Host does not have enough CPU available"; } } if (hasCapacity) { if (s_logger.isDebugEnabled()) { s_logger.debug("Host has enough CPU and RAM available"); } s_logger.debug( "STATS: Can alloc CPU from host: " + hostId + ", used: " + usedCpu + ", reserved: " + reservedCpu + ", actual total: " + actualTotalCpu + ", total with overprovisioning: " + totalCpu + "; requested cpu:" + cpu + ",alloc_from_last_host?:" + checkFromReservedCapacity + " ,considerReservedCapacity?: " + considerReservedCapacity); s_logger.debug( "STATS: Can alloc MEM from host: " + hostId + ", used: " + usedMem + ", reserved: " + reservedMem + ", total: " + totalMem + "; requested mem: " + ram + ",alloc_from_last_host?:" + checkFromReservedCapacity + " ,considerReservedCapacity?: " + considerReservedCapacity); } else { if (checkFromReservedCapacity) { s_logger.debug( "STATS: Failed to alloc resource from host: " + hostId + " reservedCpu: " + reservedCpu + ", requested cpu: " + cpu + ", reservedMem: " + reservedMem + ", requested mem: " + ram); } else { s_logger.debug( "STATS: Failed to alloc resource from host: " + hostId + " reservedCpu: " + reservedCpu + ", used cpu: " + usedCpu + ", requested cpu: " + cpu + ", actual total cpu: " + actualTotalCpu + ", total cpu with overprovisioning: " + totalCpu + ", reservedMem: " + reservedMem + ", used Mem: " + usedMem + ", requested mem: " + ram + ", total Mem:" + totalMem + " ,considerReservedCapacity?: " + considerReservedCapacity); } if (s_logger.isDebugEnabled()) { s_logger.debug(failureReason + ", cannot allocate to this host."); } } return hasCapacity; }
@DB @Override public boolean releaseVmCapacity( VirtualMachine vm, boolean moveFromReserved, boolean moveToReservered, Long hostId) { ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId()); CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU); CapacityVO capacityMemory = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY); Long clusterId = null; if (hostId != null) { HostVO host = _hostDao.findById(hostId); clusterId = host.getClusterId(); } if (capacityCpu == null || capacityMemory == null || svo == null) { return false; } Transaction txn = Transaction.currentTxn(); try { txn.start(); capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true); capacityMemory = _capacityDao.lockRow(capacityMemory.getId(), true); long usedCpu = capacityCpu.getUsedCapacity(); long usedMem = capacityMemory.getUsedCapacity(); long reservedCpu = capacityCpu.getReservedCapacity(); long reservedMem = capacityMemory.getReservedCapacity(); long actualTotalCpu = capacityCpu.getTotalCapacity(); float cpuOvercommitRatio = Float.parseFloat( _clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio").getValue()); float memoryOvercommitRatio = Float.parseFloat( _clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio").getValue()); int vmCPU = (int) (svo.getCpu() * svo.getSpeed()); long vmMem = (long) (svo.getRamSize() * 1024L * 1024L); long actualTotalMem = capacityMemory.getTotalCapacity(); long totalMem = (long) (actualTotalMem * memoryOvercommitRatio); long totalCpu = (long) (actualTotalCpu * cpuOvercommitRatio); if (s_logger.isDebugEnabled()) { s_logger.debug( "Hosts's actual total CPU: " + actualTotalCpu + " and CPU after applying overprovisioning: " + totalCpu); s_logger.debug( "Hosts's actual total RAM: " + actualTotalMem + " and RAM after applying overprovisioning: " + totalMem); } if (!moveFromReserved) { /* move resource from used */ if (usedCpu >= vmCPU) { capacityCpu.setUsedCapacity(usedCpu - vmCPU); } if (usedMem >= vmMem) { capacityMemory.setUsedCapacity(usedMem - vmMem); } if (moveToReservered) { if (reservedCpu + vmCPU <= totalCpu) { capacityCpu.setReservedCapacity(reservedCpu + vmCPU); } if (reservedMem + vmMem <= totalMem) { capacityMemory.setReservedCapacity(reservedMem + vmMem); } } } else { if (reservedCpu >= vmCPU) { capacityCpu.setReservedCapacity(reservedCpu - vmCPU); } if (reservedMem >= vmMem) { capacityMemory.setReservedCapacity(reservedMem - vmMem); } } s_logger.debug( "release cpu from host: " + hostId + ", old used: " + usedCpu + ",reserved: " + reservedCpu + ", actual total: " + actualTotalCpu + ", total with overprovisioning: " + totalCpu + "; new used: " + capacityCpu.getUsedCapacity() + ",reserved:" + capacityCpu.getReservedCapacity() + "; movedfromreserved: " + moveFromReserved + ",moveToReservered" + moveToReservered); s_logger.debug( "release mem from host: " + hostId + ", old used: " + usedMem + ",reserved: " + reservedMem + ", total: " + totalMem + "; new used: " + capacityMemory.getUsedCapacity() + ",reserved:" + capacityMemory.getReservedCapacity() + "; movedfromreserved: " + moveFromReserved + ",moveToReservered" + moveToReservered); _capacityDao.update(capacityCpu.getId(), capacityCpu); _capacityDao.update(capacityMemory.getId(), capacityMemory); txn.commit(); return true; } catch (Exception e) { s_logger.debug("Failed to transit vm's state, due to " + e.getMessage()); txn.rollback(); return false; } }