engine: optimise CPU and DB hotspot to return enabled hypervisors in the zone

This refactors a ResourceManager::listAvailHypervisorInZone method
that should return unique hypervisors for which existing hosts are Up
and processed. We can approximate this by assuming that those hosts
would have setup their hypervisor-specific systemvmtemplates. In a given
environment there wouldn't be thousands of systemvmtemplates, but can
have thousands of hosts. So, instead of scanning the entire cloud.host
table, we can make calculate guess by returning unique hypervisors of
systemvm templates which are ready. This method was used in
::processConnect() when an agent joins, to speed up its handling.

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Rohit Yadav 2024-05-10 00:06:58 +05:30
parent 8a320b807d
commit 5603bf9c1a
7 changed files with 22 additions and 28 deletions

View File

@ -132,7 +132,7 @@ public interface ResourceManager extends ResourceService, Configurable {
public List<HostVO> listAllHostsInAllZonesByType(Type type);
public List<HypervisorType> listAvailHypervisorInZone(Long hostId, Long zoneId);
public List<HypervisorType> listAvailHypervisorInZone(Long zoneId);
public HostVO findHostByGuid(String guid);

View File

@ -67,6 +67,8 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long>, StateDao<
public List<VMTemplateVO> userIsoSearch(boolean listRemoved);
List<VMTemplateVO> listAllReadySystemVMTemplates(Long zoneId);
VMTemplateVO findSystemVMTemplate(long zoneId);
VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType);

View File

@ -551,17 +551,22 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
}
@Override
public VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType) {
public List<VMTemplateVO> listAllReadySystemVMTemplates(Long zoneId) {
SearchCriteria<VMTemplateVO> sc = readySystemTemplateSearch.create();
sc.setParameters("templateType", Storage.TemplateType.SYSTEM);
sc.setParameters("state", VirtualMachineTemplate.State.Active);
sc.setJoinParameters("tmplHyper", "type", Host.Type.Routing);
sc.setJoinParameters("tmplHyper", "zoneId", zoneId);
if (zoneId != null) {
sc.setJoinParameters("tmplHyper", "zoneId", zoneId);
}
sc.setJoinParameters("vmTemplateJoinTemplateStoreRef", "downloadState", new VMTemplateStorageResourceAssoc.Status[] {VMTemplateStorageResourceAssoc.Status.DOWNLOADED, VMTemplateStorageResourceAssoc.Status.BYPASSED});
// order by descending order of id
List<VMTemplateVO> tmplts = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, null));
return listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, null));
}
@Override
public VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType) {
List<VMTemplateVO> tmplts = listAllReadySystemVMTemplates(zoneId);
if (tmplts.size() > 0) {
if (hypervisorType == HypervisorType.Any) {
return tmplts.get(0);
@ -571,7 +576,6 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
return tmplt;
}
}
}
return null;
}

View File

@ -4207,7 +4207,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
// check if zone is configured, if not, just return empty list
List<HypervisorType> hypers = null;
if (!isIso) {
hypers = _resourceMgr.listAvailHypervisorInZone(null, null);
hypers = _resourceMgr.listAvailHypervisorInZone(null);
if (hypers == null || hypers.isEmpty()) {
return new Pair<List<TemplateJoinVO>, Integer>(new ArrayList<TemplateJoinVO>(), 0);
}

View File

@ -32,6 +32,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
@ -3275,26 +3276,13 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
}
@Override
public List<HypervisorType> listAvailHypervisorInZone(final Long hostId, final Long zoneId) {
final SearchCriteria<String> sc = _hypervisorsInDC.create();
if (zoneId != null) {
sc.setParameters("dataCenter", zoneId);
public List<HypervisorType> listAvailHypervisorInZone(final Long zoneId) {
List<VMTemplateVO> systemVMTemplates = _templateDao.listAllReadySystemVMTemplates(zoneId);
final Set<HypervisorType> hypervisors = new HashSet<>();
for (final VMTemplateVO systemVMTemplate : systemVMTemplates) {
hypervisors.add(systemVMTemplate.getHypervisorType());
}
if (hostId != null) {
// exclude the given host, since we want to check what hypervisor is already handled
// in adding this new host
sc.setParameters("id", hostId);
}
sc.setParameters("type", Host.Type.Routing);
// The search is not able to return list of enums, so getting
// list of hypervisors as strings and then converting them to enum
final List<String> hvs = _hostDao.customSearch(sc, null);
final List<HypervisorType> hypervisors = new ArrayList<HypervisorType>();
for (final String hv : hvs) {
hypervisors.add(HypervisorType.getType(hv));
}
return hypervisors;
return new ArrayList<>(hypervisors);
}
@Override

View File

@ -275,7 +275,7 @@ public class DownloadListener implements Listener {
@Override
public void processConnect(Host agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
if (cmd instanceof StartupRoutingCommand) {
List<HypervisorType> hypers = _resourceMgr.listAvailHypervisorInZone(agent.getId(), agent.getDataCenterId());
List<HypervisorType> hypers = _resourceMgr.listAvailHypervisorInZone(agent.getDataCenterId());
HypervisorType hostHyper = agent.getHypervisorType();
if (hypers.contains(hostHyper)) {
return;

View File

@ -438,7 +438,7 @@ public class MockResourceManagerImpl extends ManagerBase implements ResourceMana
* @see com.cloud.resource.ResourceManager#listAvailHypervisorInZone(java.lang.Long, java.lang.Long)
*/
@Override
public List<HypervisorType> listAvailHypervisorInZone(final Long hostId, final Long zoneId) {
public List<HypervisorType> listAvailHypervisorInZone(final Long zoneId) {
// TODO Auto-generated method stub
return null;
}