mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
Bug 11617: Ensure the Deployment planner is choosing clusters based on aggregate capacity
Changes: - We were ordering clusters based on capacity of the first-fit host found in each cluster. Due to this, there were cases where we deployed VMs to one cluster instead of balancing off within clusters. - Now we order the list of clusters by aggregate capacity and choose the ones that have enough capacity for the required VM in this order. - This should balance the load between clusters instead of bombarding one. Conflicts: server/src/com/cloud/capacity/dao/CapacityDao.java server/src/com/cloud/capacity/dao/CapacityDaoImpl.java
This commit is contained in:
parent
eacb9dde26
commit
e0a179752d
@ -21,16 +21,16 @@ package com.cloud.capacity.dao;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.capacity.CapacityVO;
|
||||
import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface CapacityDao extends GenericDao<CapacityVO, Long> {
|
||||
CapacityVO findByHostIdType(Long hostId, short capacityType);
|
||||
List<Long> orderClustersInZoneOrPodByHostCapacities(long id, int requiredCpu, long requiredRam, short capacityTypeForOrdering, boolean isZone, float cpuOverprovisioningFactor);
|
||||
List<Long> listClustersInZoneOrPodByHostCapacities(long id, int requiredCpu, long requiredRam, short capacityTypeForOrdering, boolean isZone, float cpuOverprovisioningFactor);
|
||||
List<Long> listHostsWithEnoughCapacity(int requiredCpu, long requiredRam, Long clusterId, String hostType, float cpuOverprovisioningFactor);
|
||||
List<SummedCapacity> findCapacityByType(short capacityType, Long zoneId, Long podId,
|
||||
Long clusterId, Long startIndex, Long pageSize);
|
||||
boolean removeBy(Short capacityType, Long zoneId, Long podId, Long clusterId);
|
||||
List<SummedCapacity> findByClusterPodZone(Long zoneId, Long podId, Long clusterId);
|
||||
List<SummedCapacity> findNonSharedStorageForClusterPodZone(Long zoneId,Long podId, Long clusterId);
|
||||
List<Long> orderClustersByAggregateCapacity(long id, short capacityType, boolean isZone, float cpuOverprovisioningFactor);
|
||||
}
|
||||
|
||||
@ -30,20 +30,16 @@ import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.capacity.Capacity;
|
||||
import com.cloud.capacity.CapacityVO;
|
||||
import com.cloud.host.dao.HostDaoImpl;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.StoragePoolVO;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.dao.StoragePoolDao;
|
||||
import com.cloud.storage.dao.StoragePoolDaoImpl;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.GenericSearchBuilder;
|
||||
import com.cloud.utils.db.JoinBuilder;
|
||||
import com.cloud.utils.db.JoinBuilder.JoinType;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.JoinBuilder.JoinType;
|
||||
import com.cloud.utils.db.SearchCriteria.Func;
|
||||
import com.cloud.utils.db.SearchCriteria.Op;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
@ -59,18 +55,22 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
|
||||
private static final String LIST_CLUSTERSINZONE_BY_HOST_CAPACITIES_PART1 = "SELECT DISTINCT capacity.cluster_id FROM `cloud`.`op_host_capacity` capacity INNER JOIN `cloud`.`cluster` cluster on (cluster.id = capacity.cluster_id AND cluster.removed is NULL) WHERE ";
|
||||
private static final String LIST_CLUSTERSINZONE_BY_HOST_CAPACITIES_PART2 = " AND capacity_type = ? AND ((total_capacity * ?) - used_capacity + reserved_capacity) >= ? " +
|
||||
"AND cluster_id IN (SELECT distinct cluster_id FROM `cloud`.`op_host_capacity` WHERE ";
|
||||
private static final String LIST_CLUSTERSINZONE_BY_HOST_CAPACITIES_PART3 = " AND capacity_type = ? AND ((total_capacity * ?) - used_capacity + reserved_capacity) >= ?) " +
|
||||
"ORDER BY ((total_capacity * ?) - used_capacity + reserved_capacity) DESC";
|
||||
private static final String LIST_CLUSTERSINZONE_BY_HOST_CAPACITIES_PART3 = " AND capacity_type = ? AND ((total_capacity * ?) - used_capacity + reserved_capacity) >= ?) ";
|
||||
|
||||
private SearchBuilder<CapacityVO> _hostIdTypeSearch;
|
||||
private SearchBuilder<CapacityVO> _hostOrPoolIdSearch;
|
||||
private final SearchBuilder<CapacityVO> _hostIdTypeSearch;
|
||||
private final SearchBuilder<CapacityVO> _hostOrPoolIdSearch;
|
||||
protected GenericSearchBuilder<CapacityVO, SummedCapacity> SummedCapacitySearch;
|
||||
private SearchBuilder<CapacityVO> _allFieldsSearch;
|
||||
protected final StoragePoolDaoImpl _storagePoolDao = ComponentLocator.inject(StoragePoolDaoImpl.class);
|
||||
|
||||
|
||||
private static final String LIST_HOSTS_IN_CLUSTER_WITH_ENOUGH_CAPACITY = "SELECT a.host_id FROM (host JOIN op_host_capacity a ON host.id = a.host_id AND host.cluster_id = ? AND host.type = ? " +
|
||||
private static final String LIST_HOSTS_IN_CLUSTER_WITH_ENOUGH_CAPACITY = "SELECT a.host_id FROM (host JOIN op_host_capacity a ON host.id = a.host_id AND host.cluster_id = ? AND host.type = ? " +
|
||||
"AND (a.total_capacity * ? - a.used_capacity) >= ? and a.capacity_type = 1) " +
|
||||
"JOIN op_host_capacity b ON a.host_id = b.host_id AND b.total_capacity - b.used_capacity >= ? AND b.capacity_type = 0";
|
||||
|
||||
private static final String ORDER_CLUSTERS_BY_AGGREGATE_CAPACITY_PART1 = "SELECT cluster_id FROM `cloud`.`op_host_capacity` WHERE " ;
|
||||
private static final String ORDER_CLUSTERS_BY_AGGREGATE_CAPACITY_PART2 = " AND capacity_type = ? GROUP BY cluster_id ORDER BY SUM(used_capacity+reserved_capacity)/SUM(total_capacity * ?) ASC";
|
||||
|
||||
|
||||
public CapacityDaoImpl() {
|
||||
_hostIdTypeSearch = createSearchBuilder();
|
||||
@ -164,7 +164,7 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> orderClustersInZoneOrPodByHostCapacities(long id, int requiredCpu, long requiredRam, short capacityTypeForOrdering, boolean isZone, float cpuOverprovisioningFactor){
|
||||
public List<Long> listClustersInZoneOrPodByHostCapacities(long id, int requiredCpu, long requiredRam, short capacityTypeForOrdering, boolean isZone, float cpuOverprovisioningFactor){
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
PreparedStatement pstmt = null;
|
||||
List<Long> result = new ArrayList<Long>();
|
||||
@ -187,27 +187,15 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql.toString());
|
||||
pstmt.setLong(1, id);
|
||||
if(capacityTypeForOrdering == CapacityVO.CAPACITY_TYPE_CPU){
|
||||
pstmt.setShort(2, CapacityVO.CAPACITY_TYPE_CPU);
|
||||
pstmt.setFloat(3, cpuOverprovisioningFactor);
|
||||
pstmt.setLong(4, requiredCpu);
|
||||
pstmt.setLong(5, id);
|
||||
pstmt.setShort(6, CapacityVO.CAPACITY_TYPE_MEMORY);
|
||||
pstmt.setFloat(7, 1);
|
||||
pstmt.setLong(8, requiredRam);
|
||||
pstmt.setFloat(9, cpuOverprovisioningFactor);
|
||||
}else{
|
||||
pstmt.setShort(2, CapacityVO.CAPACITY_TYPE_MEMORY);
|
||||
pstmt.setFloat(3, 1);
|
||||
pstmt.setLong(4, requiredRam);
|
||||
pstmt.setLong(5, id);
|
||||
pstmt.setShort(6, CapacityVO.CAPACITY_TYPE_CPU);
|
||||
pstmt.setFloat(7, cpuOverprovisioningFactor);
|
||||
pstmt.setLong(8, requiredCpu);
|
||||
pstmt.setFloat(9, 1);
|
||||
}
|
||||
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
pstmt.setShort(2, CapacityVO.CAPACITY_TYPE_CPU);
|
||||
pstmt.setFloat(3, cpuOverprovisioningFactor);
|
||||
pstmt.setLong(4, requiredCpu);
|
||||
pstmt.setLong(5, id);
|
||||
pstmt.setShort(6, CapacityVO.CAPACITY_TYPE_MEMORY);
|
||||
pstmt.setFloat(7, 1);
|
||||
pstmt.setLong(8, requiredRam);
|
||||
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
result.add(rs.getLong(1));
|
||||
}
|
||||
@ -363,4 +351,41 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
|
||||
|
||||
return remove(sc) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> orderClustersByAggregateCapacity(long id, short capacityTypeForOrdering, boolean isZone, float cpuOverprovisioningFactor){
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
PreparedStatement pstmt = null;
|
||||
List<Long> result = new ArrayList<Long>();
|
||||
|
||||
StringBuilder sql = new StringBuilder(ORDER_CLUSTERS_BY_AGGREGATE_CAPACITY_PART1);
|
||||
|
||||
if(isZone){
|
||||
sql.append("data_center_id = ?");
|
||||
}else{
|
||||
sql.append("pod_id = ?");
|
||||
}
|
||||
sql.append(ORDER_CLUSTERS_BY_AGGREGATE_CAPACITY_PART2);
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql.toString());
|
||||
pstmt.setLong(1, id);
|
||||
pstmt.setShort(2, capacityTypeForOrdering);
|
||||
|
||||
if(capacityTypeForOrdering == CapacityVO.CAPACITY_TYPE_CPU){
|
||||
pstmt.setFloat(3, cpuOverprovisioningFactor);
|
||||
}else{
|
||||
pstmt.setFloat(3, 1);
|
||||
}
|
||||
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
result.add(rs.getLong(1));
|
||||
}
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
throw new CloudRuntimeException("DB Exception on: " + sql, e);
|
||||
} catch (Throwable e) {
|
||||
throw new CloudRuntimeException("Caught: " + sql, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -458,9 +458,9 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
//look at the aggregate available cpu and ram per cluster
|
||||
//although an aggregate value may be false indicator that a cluster can host a vm, it will at the least eliminate those clusters which definitely cannot
|
||||
|
||||
//we need clusters having enough cpu AND RAM
|
||||
//we need clusters having enough cpu AND RAM to host this particular VM and order them by aggregate cluster capacity
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Listing clusters that have enough aggregate CPU and RAM capacity under this "+(isZone ? "Zone: " : "Pod: " )+id);
|
||||
s_logger.debug("Listing clusters in order of aggregate capacity, that have (atleast one host with) enough CPU and RAM capacity under this "+(isZone ? "Zone: " : "Pod: " )+id);
|
||||
}
|
||||
String capacityTypeToOrder = _configDao.getValue(Config.HostCapacityTypeToOrderClusters.key());
|
||||
short capacityType = CapacityVO.CAPACITY_TYPE_CPU;
|
||||
@ -471,11 +471,22 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("CPUOverprovisioningFactor considered: " + cpuOverprovisioningFactor);
|
||||
}
|
||||
List<Long> clusterIdswithEnoughCapacity = _capacityDao.orderClustersInZoneOrPodByHostCapacities(id, requiredCpu, requiredRam, capacityType, isZone, cpuOverprovisioningFactor);
|
||||
List<Long> clusterIdswithEnoughCapacity = _capacityDao.listClustersInZoneOrPodByHostCapacities(id, requiredCpu, requiredRam, capacityType, isZone, cpuOverprovisioningFactor);
|
||||
if (s_logger.isTraceEnabled()) {
|
||||
s_logger.trace("ClusterId List having enough aggregate capacity: " + clusterIdswithEnoughCapacity);
|
||||
s_logger.trace("ClusterId List having enough CPU and RAM capacity: " + clusterIdswithEnoughCapacity);
|
||||
}
|
||||
return clusterIdswithEnoughCapacity;
|
||||
List<Long> clusterIdsOrderedByAggregateCapacity = _capacityDao.orderClustersByAggregateCapacity(id, capacityType, isZone, cpuOverprovisioningFactor);
|
||||
//only keep the clusters that have enough capacity to host this VM
|
||||
if (s_logger.isTraceEnabled()) {
|
||||
s_logger.trace("ClusterId List in order of aggregate capacity: " + clusterIdsOrderedByAggregateCapacity);
|
||||
}
|
||||
clusterIdsOrderedByAggregateCapacity.retainAll(clusterIdswithEnoughCapacity);
|
||||
|
||||
if (s_logger.isTraceEnabled()) {
|
||||
s_logger.trace("ClusterId List having enough CPU and RAM capacity & in order of aggregate capacity: " + clusterIdsOrderedByAggregateCapacity);
|
||||
}
|
||||
|
||||
return clusterIdsOrderedByAggregateCapacity;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user