Skip to content

Commit a50cf61

Browse files
committed
bug CS-15278: For removing clusters crossing threshold find out the list of cluster through db instead of iteratting cluster one by one in the java code.
1 parent 94d8eb7 commit a50cf61

4 files changed

Lines changed: 93 additions & 35 deletions

File tree

api/src/com/cloud/deploy/DeploymentPlanner.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package com.cloud.deploy;
1818

19+
import java.util.Collection;
1920
import java.util.HashSet;
2021
import java.util.Set;
2122

@@ -180,6 +181,13 @@ public void addCluster(long clusterId) {
180181
_clusterIds.add(clusterId);
181182
}
182183

184+
public void addClusterList(Collection<Long> clusterList) {
185+
if (_clusterIds == null) {
186+
_clusterIds = new HashSet<Long>();
187+
}
188+
_clusterIds.addAll(clusterList);
189+
}
190+
183191
public void addHost(long hostId) {
184192
if (_hostIds == null) {
185193
_hostIds = new HashSet<Long>();

server/src/com/cloud/capacity/dao/CapacityDao.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,5 @@ List<SummedCapacity> findCapacityBy(Integer capacityType, Long zoneId,
4141
List<SummedCapacity> listCapacitiesGroupedByLevelAndType(Integer capacityType, Long zoneId, Long podId, Long clusterId, int level, Long limit);
4242
void updateCapacityState(Long dcId, Long podId, Long clusterId,
4343
Long hostId, String capacityState);
44-
}
44+
List<Long> listClustersCrossingThreshold(short capacityType, Long zoneId, Float disableThreshold, long computeRequested, Float overProvFactor);
45+
}

server/src/com/cloud/capacity/dao/CapacityDaoImpl.java

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.cloud.storage.StoragePoolVO;
3535
import com.cloud.storage.dao.StoragePoolDaoImpl;
3636
import com.cloud.utils.Pair;
37+
import com.cloud.utils.StringUtils;
3738
import com.cloud.utils.component.ComponentLocator;
3839
import com.cloud.utils.db.Filter;
3940
import com.cloud.utils.db.GenericDaoBase;
@@ -108,7 +109,12 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
108109
"WHERE total_capacity > 0 AND cluster_id is not null AND capacity_state='Enabled'";
109110
private static final String LIST_CAPACITY_GROUP_BY_CLUSTER_TYPE_PART2 = " GROUP BY cluster_id, capacity_type order by percent desc limit ";
110111
private static final String UPDATE_CAPACITY_STATE = "UPDATE `cloud`.`op_host_capacity` SET capacity_state = ? WHERE ";
111-
112+
private static final String LIST_CLUSTERS_CROSSING_THRESHOLD = "SELECT cluster_id " +
113+
"FROM (SELECT cluster_id, ( (sum(capacity.used_capacity) + sum(capacity.reserved_capacity) + ?)/sum(total_capacity) ) ratio "+
114+
"FROM `cloud`.`op_host_capacity` capacity "+
115+
"WHERE capacity.data_center_id = ? AND capacity.capacity_type = ? AND capacity.total_capacity > 0 "+
116+
"GROUP BY cluster_id) tmp " +
117+
"WHERE tmp.ratio > ? ";
112118

113119

114120
public CapacityDaoImpl() {
@@ -132,6 +138,52 @@ public CapacityDaoImpl() {
132138

133139
_allFieldsSearch.done();
134140
}
141+
142+
@Override
143+
public List<Long> listClustersCrossingThreshold(short capacityType, Long zoneId, Float disableThreshold, long compute_requested, Float overProvFactor){
144+
145+
Transaction txn = Transaction.currentTxn();
146+
PreparedStatement pstmt = null;
147+
List<Long> result = new ArrayList<Long>();
148+
StringBuilder sql = new StringBuilder(LIST_CLUSTERS_CROSSING_THRESHOLD);
149+
150+
151+
try {
152+
pstmt = txn.prepareAutoCloseStatement(sql.toString());
153+
pstmt.setLong(1, compute_requested);
154+
pstmt.setLong(2, zoneId);
155+
pstmt.setShort(3, capacityType);
156+
pstmt.setFloat(4, disableThreshold*overProvFactor);
157+
158+
ResultSet rs = pstmt.executeQuery();
159+
while (rs.next()) {
160+
result.add(rs.getLong(1));
161+
}
162+
return result;
163+
} catch (SQLException e) {
164+
throw new CloudRuntimeException("DB Exception on: " + sql, e);
165+
} catch (Throwable e) {
166+
throw new CloudRuntimeException("Caught: " + sql, e);
167+
}
168+
}
169+
170+
/*public static String preparePlaceHolders(int length) {
171+
StringBuilder builder = new StringBuilder();
172+
for (int i = 0; i < length;) {
173+
builder.append("?");
174+
if (++i < length) {
175+
builder.append(",");
176+
}
177+
}
178+
return builder.toString();
179+
}
180+
181+
public static void setValues(PreparedStatement preparedStatement, Object... values) throws SQLException {
182+
for (int i = 0; i < values.length; i++) {
183+
preparedStatement.setObject(i + 1, values[i]);
184+
}
185+
}*/
186+
135187

136188
@Override
137189
public List<SummedCapacity> findCapacityBy(Integer capacityType, Long zoneId, Long podId, Long clusterId, String resource_state){

server/src/com/cloud/deploy/FirstFitPlanner.java

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import com.cloud.user.AccountManager;
7474
import com.cloud.utils.NumbersUtil;
7575
import com.cloud.utils.Pair;
76+
import com.cloud.utils.StringUtils;
7677
import com.cloud.utils.component.Adapters;
7778
import com.cloud.utils.component.Inject;
7879
import com.cloud.vm.DiskProfile;
@@ -457,7 +458,7 @@ private List<Short> getCapacitiesForCheckingThreshold(){
457458
return capacityList;
458459
}
459460

460-
private void removeClustersCrossingThreshold(List<Long> clusterList, ExcludeList avoid, VirtualMachineProfile<? extends VirtualMachine> vmProfile){
461+
private void removeClustersCrossingThreshold(List<Long> clusterListForVmAllocation, ExcludeList avoid, VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan){
461462

462463
Map<Short,Float> capacityThresholdMap = getCapacityThresholdMap();
463464
List<Short> capacityList = getCapacitiesForCheckingThreshold();
@@ -467,37 +468,33 @@ private void removeClustersCrossingThreshold(List<Long> clusterList, ExcludeList
467468
int cpu_requested = offering.getCpu() * offering.getSpeed();
468469
long ram_requested = offering.getRamSize() * 1024L * 1024L;
469470

470-
// Iterate over the cluster List and check for each cluster whether it breaks disable threshold for any of the capacity types
471-
for (Long clusterId : clusterList){
472-
for(short capacity : capacityList){
473-
474-
List<SummedCapacity> summedCapacityList = _capacityDao.findCapacityBy(new Integer(capacity), null, null, clusterId);
475-
if (summedCapacityList != null && summedCapacityList.size() != 0 && summedCapacityList.get(0).getTotalCapacity() != 0){
476-
477-
double used = (double)(summedCapacityList.get(0).getUsedCapacity() + summedCapacityList.get(0).getReservedCapacity());
478-
double total = summedCapacityList.get(0).getTotalCapacity();
479-
480-
if (capacity == Capacity.CAPACITY_TYPE_CPU){
481-
total = total * ApiDBUtils.getCpuOverprovisioningFactor();
482-
used = used + cpu_requested;
483-
}else{
484-
used = used + ram_requested;
485-
}
486-
487-
double usedPercentage = used/total;
488-
if ( usedPercentage > capacityThresholdMap.get(capacity)){
489-
avoid.addCluster(clusterId);
490-
clustersCrossingThreshold.add(clusterId);
491-
s_logger.debug("Cannot allocate cluster " + clusterId + " for vm creation since its allocated percentage: " +usedPercentage +
492-
" will cross the disable capacity threshold: " + capacityThresholdMap.get(capacity) + " for capacity Type : " + capacity + ", skipping this cluster");
493-
break;
494-
}
495-
}
496-
}
497-
}
498-
499-
clusterList.removeAll(clustersCrossingThreshold);
500-
471+
// For each capacity get the cluster list crossing the threshold and remove it from the clusterList that will be used for vm allocation.
472+
for(short capacity : capacityList){
473+
474+
if (clusterListForVmAllocation == null || clusterListForVmAllocation.size() == 0){
475+
return;
476+
}
477+
478+
if (capacity == Capacity.CAPACITY_TYPE_CPU){
479+
clustersCrossingThreshold = _capacityDao.listClustersCrossingThreshold(Capacity.CAPACITY_TYPE_CPU, plan.getDataCenterId(),
480+
capacityThresholdMap.get(capacity), cpu_requested, ApiDBUtils.getCpuOverprovisioningFactor());
481+
}else{
482+
clustersCrossingThreshold = _capacityDao.listClustersCrossingThreshold(capacity, plan.getDataCenterId(),
483+
capacityThresholdMap.get(capacity), ram_requested, 1.0f);//Mem overprov not supported yet
484+
}
485+
486+
487+
if (clustersCrossingThreshold != null && clustersCrossingThreshold.size() != 0){
488+
// addToAvoid Set
489+
avoid.addClusterList(clustersCrossingThreshold);
490+
// Remove clusters crossing disabled threshold
491+
clusterListForVmAllocation.removeAll(clustersCrossingThreshold);
492+
493+
s_logger.debug("Cannot allocate cluster list " + clustersCrossingThreshold.toString() + " for vm creation since their allocated percentage" +
494+
" crosses the disable capacity threshold: " + capacityThresholdMap.get(capacity) + " for capacity Type : " + capacity + ", skipping these clusters");
495+
}
496+
497+
}
501498
}
502499

503500
private DeployDestination checkClustersforDestination(List<Long> clusterList, VirtualMachineProfile<? extends VirtualMachine> vmProfile,
@@ -507,7 +504,7 @@ private DeployDestination checkClustersforDestination(List<Long> clusterList, Vi
507504
s_logger.trace("ClusterId List to consider: " + clusterList);
508505
}
509506

510-
removeClustersCrossingThreshold(clusterList, avoid, vmProfile);
507+
removeClustersCrossingThreshold(clusterList, avoid, vmProfile, plan);
511508

512509
for(Long clusterId : clusterList){
513510
Cluster clusterVO = _clusterDao.findById(clusterId);

0 commit comments

Comments
 (0)