weizhouapache commented on code in PR #10997: URL: https://github.com/apache/cloudstack/pull/10997#discussion_r2149409089
########## server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java: ########## @@ -407,6 +405,54 @@ private List<? extends Host> reorderHostsByCapacity(DeploymentPlan plan, List<? return reorderedHosts; } + private Pair<List<Long>, Map<Long, Double>> getOrderedHostsByCapacity(Long zoneId, Long clusterId) { + double cpuToMemoryWeight = ConfigurationManager.HostCapacityTypeCpuMemoryWeight.value(); + // Get capacity by which we should reorder + short capacityType = getCapacityType(cpuToMemoryWeight); + if (capacityType >= 0) { // for CPU or RAM + return _capacityDao.orderHostsByFreeCapacity(zoneId, clusterId, capacityType); + } + List<CapacityVO> capacities = _capacityDao.listHostCapacityByCapacityTypes(zoneId, clusterId, + List.of(Capacity.CAPACITY_TYPE_CPU, Capacity.CAPACITY_TYPE_MEMORY)); + Map<Long, Double> hostByComputedCapacity = getHostByCombinedCapacities(capacities, cpuToMemoryWeight); + return new Pair<>(new ArrayList<>(hostByComputedCapacity.keySet()), hostByComputedCapacity); + } + + short getCapacityType(double cpuToMemoryWeight) { + String capacityTypeToOrder = _configDao.getValue(Config.HostCapacityTypeToOrderClusters.key()); + short capacityType = CapacityVO.CAPACITY_TYPE_CPU; + if (ApiConstants.RAM.equalsIgnoreCase(capacityTypeToOrder)){ + capacityType = CapacityVO.CAPACITY_TYPE_MEMORY; + } else if (ApiConstants.COMBINED_CAPACITY_ORDERING.equalsIgnoreCase(capacityTypeToOrder)) { + capacityType = -1; + } + Review Comment: the method should return if capacityType > 0 here ########## server/src/main/java/com/cloud/deploy/FirstFitPlanner.java: ########## @@ -517,6 +514,91 @@ protected Pair<List<Long>, Map<Long, Double>> listPodsByCapacity(long zoneId, in } + private Pair<List<Long>, Map<Long, Double>> getOrderedPodsByCapacity(long zoneId) { + double cpuToMemoryWeight = ConfigurationManager.HostCapacityTypeCpuMemoryWeight.value(); + short capacityType = getCapacityType(cpuToMemoryWeight); + if (capacityType >= 0) { // for capacityType other than COMBINED + return capacityDao.orderPodsByAggregateCapacity(zoneId, capacityType); + } + List<CapacityVO> capacities = capacityDao.listPodCapacityByCapacityTypes(zoneId, List.of(Capacity.CAPACITY_TYPE_CPU, Capacity.CAPACITY_TYPE_MEMORY)); + Map<Long, Double> podsByCombinedCapacities = getPodByCombinedCapacities(capacities, cpuToMemoryWeight); + return new Pair<>(new ArrayList<>(podsByCombinedCapacities.keySet()), podsByCombinedCapacities); + } + + // order pods by combining cpu and memory capacity considering cpuToMemoeryWeight + private Map<Long, Double> getPodByCombinedCapacities(List<CapacityVO> capacities, double cpuToMemoryWeight) { + Map<Long, Double> podByCombinedCapacity = new HashMap<>(); + for (CapacityVO capacityVO : capacities) { + boolean isCPUCapacity = capacityVO.getCapacityType() == Capacity.CAPACITY_TYPE_CPU; + long podId = capacityVO.getPodId(); + double applicableWeight = isCPUCapacity ? cpuToMemoryWeight : 1 - cpuToMemoryWeight; + String overCommitRatioParam = isCPUCapacity ? ApiConstants.CPU_OVERCOMMIT_RATIO : ApiConstants.MEMORY_OVERCOMMIT_RATIO; + ClusterDetailsVO overCommitRatioVO = clusterDetailsDao.findDetail(capacityVO.getClusterId(), overCommitRatioParam); + float overCommitRatio = Float.parseFloat(overCommitRatioVO.getValue()); + double capacityMetric = applicableWeight * + (capacityVO.getUsedCapacity() + capacityVO.getReservedCapacity())/(capacityVO.getTotalCapacity() * overCommitRatio); + podByCombinedCapacity.merge(podId, capacityMetric, Double::sum); + } + return podByCombinedCapacity.entrySet() + .stream() + .sorted(Map.Entry.comparingByValue()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); + } + + + private Pair<List<Long>, Map<Long, Double>> getOrderedClustersByCapacity(long id, long vmId, boolean isZone) { + double cpuToMemoryWeight = ConfigurationManager.HostCapacityTypeCpuMemoryWeight.value(); + short capacityType = getCapacityType(cpuToMemoryWeight); + if (capacityType >= 0) { // for capacityType other than COMBINED + return capacityDao.orderClustersByAggregateCapacity(id, vmId, capacityType, isZone); + } + + Long zoneId = isZone ? id : null; + Long podId = isZone ? null : id; + List<CapacityVO> capacities = capacityDao.listClusterCapacityByCapacityTypes(zoneId, podId, vmId, + List.of(Capacity.CAPACITY_TYPE_CPU, Capacity.CAPACITY_TYPE_MEMORY)); + + Map<Long, Double> clusterByCombinedCapacities = getClusterByCombinedCapacities(capacities, cpuToMemoryWeight); + return new Pair<>(new ArrayList<>(clusterByCombinedCapacities.keySet()), clusterByCombinedCapacities); + } + + private Map<Long, Double> getClusterByCombinedCapacities(List<CapacityVO> capacities, double cpuToMemoryWeight) { + Map<Long, Double> clusterByCombinedCapacity = new HashMap<>(); + for (CapacityVO capacityVO : capacities) { + boolean isCPUCapacity = capacityVO.getCapacityType() == Capacity.CAPACITY_TYPE_CPU; + long clusterId = capacityVO.getClusterId(); + double applicableWeight = isCPUCapacity ? cpuToMemoryWeight : 1 - cpuToMemoryWeight; + String overCommitRatioParam = isCPUCapacity ? ApiConstants.CPU_OVERCOMMIT_RATIO : ApiConstants.MEMORY_OVERCOMMIT_RATIO; + ClusterDetailsVO overCommitRatioVO = clusterDetailsDao.findDetail(clusterId, overCommitRatioParam); + float overCommitRatio = Float.parseFloat(overCommitRatioVO.getValue()); + double capacityMetric = applicableWeight * + (capacityVO.getUsedCapacity() + capacityVO.getReservedCapacity())/(capacityVO.getTotalCapacity() * overCommitRatio); + clusterByCombinedCapacity.merge(clusterId, capacityMetric, Double::sum); + } + return clusterByCombinedCapacity.entrySet() + .stream() + .sorted(Map.Entry.comparingByValue()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); + } + + short getCapacityType(double cpuToMemoryWeight) { + String capacityTypeToOrder = configDao.getValue(Config.HostCapacityTypeToOrderClusters.key()); + short capacityType = CapacityVO.CAPACITY_TYPE_CPU; + if (ApiConstants.RAM.equalsIgnoreCase(capacityTypeToOrder)){ + capacityType = CapacityVO.CAPACITY_TYPE_MEMORY; + } else if (ApiConstants.COMBINED_CAPACITY_ORDERING.equalsIgnoreCase(capacityTypeToOrder)) { + capacityType = -1; + } + Review Comment: return capacityType if > 0 here ########## engine/schema/src/main/java/com/cloud/capacity/dao/CapacityDaoImpl.java: ########## @@ -1068,7 +1068,65 @@ public Pair<List<Long>, Map<Long, Double>> orderHostsByFreeCapacity(Long zoneId, } @Override - public List<Long> listPodsByHostCapacities(long zoneId, int requiredCpu, long requiredRam, short capacityType) { + public List<CapacityVO> listHostCapacityByCapacityTypes(Long zoneId, Long clusterId, List<Short> capacityTypes) { + SearchBuilder<CapacityVO> sb = createSearchBuilder(); + sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); + sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); + sb.and("capacityTypes", sb.entity().getCapacityType(), SearchCriteria.Op.IN); + sb.and("capacityState", sb.entity().getCapacityState(), Op.EQ); + sb.done(); + + SearchCriteria<CapacityVO> sc = sb.create(); + sc.setParameters("capacityState", "Enabled"); + if (zoneId != null) { + sc.setParameters("zoneId", zoneId); + } + if (clusterId != null) { + sc.setParameters("clusterId", clusterId); + } + sc.setParameters("capacityTypes", capacityTypes.toArray()); + return listBy(sc); + } + + @Override + public List<CapacityVO> listPodCapacityByCapacityTypes(Long zoneId, List<Short> capacityTypes) { + SearchBuilder<CapacityVO> sb = createSearchBuilder(); + sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); + sb.and("capacityTypes", sb.entity().getCapacityType(), SearchCriteria.Op.IN); + sb.and("capacityState", sb.entity().getCapacityState(), Op.EQ); + sb.done(); + SearchCriteria<CapacityVO> sc = sb.create(); + sc.setParameters("capacityState", "Enabled"); + if (zoneId != null) { + sc.setParameters("zoneId", zoneId); + } + sc.setParameters("capacityTypes", capacityTypes.toArray()); + return listBy(sc); + } + + @Override + public List<CapacityVO> listClusterCapacityByCapacityTypes(Long zoneId, Long podId, long vmId, List<Short> capacityTypes) { Review Comment: is `vmId` used in this method ? ########## server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java: ########## @@ -407,6 +405,54 @@ private List<? extends Host> reorderHostsByCapacity(DeploymentPlan plan, List<? return reorderedHosts; } + private Pair<List<Long>, Map<Long, Double>> getOrderedHostsByCapacity(Long zoneId, Long clusterId) { + double cpuToMemoryWeight = ConfigurationManager.HostCapacityTypeCpuMemoryWeight.value(); + // Get capacity by which we should reorder + short capacityType = getCapacityType(cpuToMemoryWeight); + if (capacityType >= 0) { // for CPU or RAM + return _capacityDao.orderHostsByFreeCapacity(zoneId, clusterId, capacityType); + } + List<CapacityVO> capacities = _capacityDao.listHostCapacityByCapacityTypes(zoneId, clusterId, + List.of(Capacity.CAPACITY_TYPE_CPU, Capacity.CAPACITY_TYPE_MEMORY)); + Map<Long, Double> hostByComputedCapacity = getHostByCombinedCapacities(capacities, cpuToMemoryWeight); + return new Pair<>(new ArrayList<>(hostByComputedCapacity.keySet()), hostByComputedCapacity); + } + + short getCapacityType(double cpuToMemoryWeight) { + String capacityTypeToOrder = _configDao.getValue(Config.HostCapacityTypeToOrderClusters.key()); + short capacityType = CapacityVO.CAPACITY_TYPE_CPU; + if (ApiConstants.RAM.equalsIgnoreCase(capacityTypeToOrder)){ + capacityType = CapacityVO.CAPACITY_TYPE_MEMORY; + } else if (ApiConstants.COMBINED_CAPACITY_ORDERING.equalsIgnoreCase(capacityTypeToOrder)) { + capacityType = -1; + } + + if (cpuToMemoryWeight == 1) { + capacityType = CapacityVO.CAPACITY_TYPE_CPU; + } + if (cpuToMemoryWeight == 0) { + capacityType = CapacityVO.CAPACITY_TYPE_MEMORY; + } + return capacityType; + } + + + @NotNull + private static Map<Long, Double> getHostByCombinedCapacities(List<CapacityVO> capacities, double cpuToMemoryWeight) { Review Comment: can you write a unit test for this method ? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@cloudstack.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org