From 0f3922f324d0ab3f231a1d0c15fc85e61bc573e4 Mon Sep 17 00:00:00 2001 From: prachi Date: Thu, 24 Mar 2011 16:57:54 -0700 Subject: [PATCH] Bug 9117: allocator performance improvements Fix for following optimization: Make PodAllocator aware of host tags. If the service offering has host_tag specified, PodAllocator can pick the pods having hosts with that tag. This would reduce the list of pods the allocator has to iterate through to find a suitable pod. Added a new PodAllocator 'HostTagBasedPodAllocator' that extends the 'UserConcentratedAllocator'. --- core/src/com/cloud/dc/dao/HostPodDao.java | 4 +- core/src/com/cloud/dc/dao/HostPodDaoImpl.java | 33 +++++++++- .../impl/HostTagBasedPodAllocator.java | 65 +++++++++++++++++++ .../impl/UserConcentratedAllocator.java | 15 +++-- 4 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 server/src/com/cloud/agent/manager/allocator/impl/HostTagBasedPodAllocator.java diff --git a/core/src/com/cloud/dc/dao/HostPodDao.java b/core/src/com/cloud/dc/dao/HostPodDao.java index 01fb2864819..55342b13dbb 100644 --- a/core/src/com/cloud/dc/dao/HostPodDao.java +++ b/core/src/com/cloud/dc/dao/HostPodDao.java @@ -30,6 +30,8 @@ public interface HostPodDao extends GenericDao { public HostPodVO findByName(String name, long dcId); - public HashMap> getCurrentPodCidrSubnets(long zoneId, long podIdToSkip); + public HashMap> getCurrentPodCidrSubnets(long zoneId, long podIdToSkip); + + public List listPodsByHostTag(long dcId, String hostTag); } diff --git a/core/src/com/cloud/dc/dao/HostPodDaoImpl.java b/core/src/com/cloud/dc/dao/HostPodDaoImpl.java index b12b5a997de..9fb12b2f850 100644 --- a/core/src/com/cloud/dc/dao/HostPodDaoImpl.java +++ b/core/src/com/cloud/dc/dao/HostPodDaoImpl.java @@ -36,6 +36,7 @@ import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; @Local(value={HostPodDao.class}) @@ -43,7 +44,11 @@ public class HostPodDaoImpl extends GenericDaoBase implements H private static final Logger s_logger = Logger.getLogger(HostPodDaoImpl.class); protected SearchBuilder DataCenterAndNameSearch; - protected SearchBuilder DataCenterIdSearch; + protected SearchBuilder DataCenterIdSearch; + + private static final String PodsByHostTag = "SELECT DISTINCT host_pod_ref.* FROM (host_tags JOIN host ON host_tags.host_id = host.id AND host_tags.tag = ?) JOIN host_pod_ref " + + "ON host_pod_ref.id = host.pod_id WHERE host_pod_ref.data_center_id = ? "; + protected HostPodDaoImpl() { DataCenterAndNameSearch = createSearchBuilder(); @@ -96,7 +101,31 @@ public class HostPodDaoImpl extends GenericDaoBase implements H } return currentPodCidrSubnets; - } + } + + @Override + public List listPodsByHostTag(long dcId, String hostTag) { + + StringBuilder sql = new StringBuilder(PodsByHostTag); + + Transaction txn = Transaction.currentTxn(); + PreparedStatement pstmt = s_initStmt; + try { + pstmt = txn.prepareAutoCloseStatement(sql.toString()); + int i = 1; + pstmt.setString(i++, hostTag); + pstmt.setLong(i++, dcId); + ResultSet rs = pstmt.executeQuery(); + List pods = new ArrayList(); + while (rs.next()) { + pods.add(toEntityBean(rs, false)); + } + return pods; + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to execute " + pstmt.toString(), e); + } + + } @Override public boolean configure(String name, Map params) throws ConfigurationException { diff --git a/server/src/com/cloud/agent/manager/allocator/impl/HostTagBasedPodAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/HostTagBasedPodAllocator.java new file mode 100644 index 00000000000..e5f423b03b6 --- /dev/null +++ b/server/src/com/cloud/agent/manager/allocator/impl/HostTagBasedPodAllocator.java @@ -0,0 +1,65 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.agent.manager.allocator.impl; + +import java.util.ArrayList; +import java.util.List; +import javax.ejb.Local; +import org.apache.log4j.Logger; +import com.cloud.agent.manager.allocator.PodAllocator; +import com.cloud.dc.HostPodVO; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.service.ServiceOffering; +import com.cloud.utils.component.Inject; + +/* + * Use this PodAllocator when the deployment is such that pod has homogeneous tags on hosts. + * If any pod can contain hosts with any tag, this optimization will not yield much benefit. + */ +@Local(value=PodAllocator.class) +public class HostTagBasedPodAllocator extends UserConcentratedAllocator { + private final static Logger s_logger = Logger.getLogger(HostTagBasedPodAllocator.class); + @Inject HostPodDao _podDao; + + public HostTagBasedPodAllocator() { + } + + @Override + protected List listPods(long zoneId, ServiceOffering offering){ + List podsInZone = new ArrayList(); + + if(offering != null && offering.getHostTag() != null){ + String hostTag = offering.getHostTag(); + podsInZone = _podDao.listPodsByHostTag(zoneId, hostTag); + + if(podsInZone.size() == 0){ + if (s_logger.isInfoEnabled()) { + s_logger.info("No Pods found in Zone: '"+zoneId+"' having Hosts with host tag: '"+ hostTag +"'"); + } + }else{ + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found "+podsInZone.size() +" Pods in Zone: '"+zoneId+"' having Hosts with host tag: '"+ hostTag +"'"); + } + } + }else{ + podsInZone = super.listPods(zoneId, offering); + } + + return podsInZone; + } +} diff --git a/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java index 5960e25abd9..89da54f3f0a 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java @@ -83,7 +83,7 @@ public class UserConcentratedAllocator implements PodAllocator { @Override public Pair allocateTo(VirtualMachineTemplate template, ServiceOfferingVO offering, DataCenterVO zone, long accountId, Set avoids) { long zoneId = zone.getId(); - List podsInZone = _podDao.listByDataCenterId(zoneId); + List podsInZone = listPods(zoneId, offering); if (podsInZone.size() == 0) { s_logger.debug("No pods found in zone " + zone.getName()); @@ -100,10 +100,7 @@ public class UserConcentratedAllocator implements PodAllocator { s_logger.debug("Checking Pod: " + podId); } - if (template != null && !templateAvailableInPod(template.getId(), pod.getDataCenterId(), podId)) { - continue; - } - + if (offering != null) { // test for enough memory in the pod (make sure to check for enough memory for the service offering, plus some extra padding for xen overhead long[] hostCandiates = new long[1]; @@ -160,6 +157,14 @@ public class UserConcentratedAllocator implements PodAllocator { return new Pair(selectedPod, podHostCandidates.get(selectedPod.getId())); } } + + protected List listPods(long zoneId, ServiceOffering offering){ + List podsInZone = _podDao.listByDataCenterId(zoneId); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found "+podsInZone.size() +" Pods in Zone: "+zoneId); + } + return podsInZone; + } private boolean dataCenterAndPodHasEnoughCapacity(long dataCenterId, long podId, long capacityNeeded, short capacityType, long[] hostCandidate) { List capacities = null;