From 337add8fb9be33b3de960fd1cc2e4eb57229f0cf Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 3 Sep 2024 16:01:46 +0530 Subject: [PATCH 01/62] server: PingRoutingCommand - apply some optimizations Signed-off-by: Abhishek Kumar --- .../cloud/vm/VirtualMachineManagerImpl.java | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 767e20db81e..e4410ff9b43 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -5037,11 +5037,20 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } private List listStalledVMInTransitionStateOnUpHost(final long hostId, final Date cutTime) { - final String sql = "SELECT i.id FROM vm_instance as i, host as h WHERE h.status = 'UP' " + - "AND h.id = ? AND i.power_state_update_time < ? AND i.host_id = h.id " + - "AND (i.state ='Starting' OR i.state='Stopping' OR i.state='Migrating') " + - "AND i.id NOT IN (SELECT w.vm_instance_id FROM vm_work_job AS w JOIN async_job AS j ON w.id = j.id WHERE j.job_status = ?)" + - "AND i.removed IS NULL"; + final String sql = "SELECT i.id\n" + + "FROM vm_instance AS i\n" + + "INNER JOIN host AS h ON i.host_id = h.id\n" + + "WHERE h.status = 'UP'\n" + + " AND h.id = ?\n" + + " AND i.power_state_update_time < ?\n" + + " AND i.state IN ('Starting', 'Stopping', 'Migrating')\n" + + " AND i.id NOT IN (\n" + + " SELECT vm_instance_id\n" + + " FROM vm_work_job AS w\n" + + " INNER JOIN async_job AS j ON w.id = j.id\n" + + " WHERE j.job_status = ?\n" + + " )\n" + + " AND i.removed IS NULL"; final List l = new ArrayList<>(); try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB)) { @@ -5063,11 +5072,17 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } private List listVMInTransitionStateWithRecentReportOnUpHost(final long hostId, final Date cutTime) { - final String sql = "SELECT i.id FROM vm_instance as i, host as h WHERE h.status = 'UP' " + - "AND h.id = ? AND i.power_state_update_time > ? AND i.host_id = h.id " + - "AND (i.state ='Starting' OR i.state='Stopping' OR i.state='Migrating') " + - "AND i.id NOT IN (SELECT w.vm_instance_id FROM vm_work_job AS w JOIN async_job AS j ON w.id = j.id WHERE j.job_status = ?)" + - "AND i.removed IS NULL"; + final String sql = "SELECT i.id\n" + + "FROM vm_instance AS i\n" + + "INNER JOIN host AS h ON i.host_id = h.id\n" + + "WHERE h.status = 'UP' \n" + + " AND h.id = ?\n" + + " AND i.power_state_update_time > ?\n" + + " AND i.state IN ('Starting', 'Stopping', 'Migrating')\n" + + " AND i.id NOT IN (SELECT vm_instance_id FROM vm_work_job AS w\n" + + " INNER JOIN async_job AS j ON w.id = j.id\n" + + " WHERE j.job_status = ?)\n" + + " AND i.removed IS NULL"; final List l = new ArrayList<>(); try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB)) { @@ -5090,11 +5105,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } private List listStalledVMInTransitionStateOnDisconnectedHosts(final Date cutTime) { - final String sql = "SELECT i.* FROM vm_instance as i, host as h WHERE h.status != 'UP' " + - "AND i.power_state_update_time < ? AND i.host_id = h.id " + - "AND (i.state ='Starting' OR i.state='Stopping' OR i.state='Migrating') " + - "AND i.id NOT IN (SELECT w.vm_instance_id FROM vm_work_job AS w JOIN async_job AS j ON w.id = j.id WHERE j.job_status = ?)" + - "AND i.removed IS NULL"; + final String sql = "SELECT i.*\n" + + "FROM vm_instance AS i\n" + + "INNER JOIN host AS h ON i.host_id = h.id\n" + + "WHERE h.status != 'UP' \n" + + " AND i.power_state_update_time < ?\n" + + " AND i.state IN ('Starting', 'Stopping', 'Migrating')\n" + + " AND i.id NOT IN (SELECT vm_instance_id FROM vm_work_job AS w\n" + + " INNER JOIN async_job AS j ON w.id = j.id\n" + + " WHERE j.job_status = ?)\n" + + " AND i.removed IS NUL"; final List l = new ArrayList<>(); try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB)) { From 1be848da2502f279ab8f2bb5f4df560a94103d21 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 3 Sep 2024 16:03:11 +0530 Subject: [PATCH 02/62] server: PingRoutingCommand - enable scanStalledVm Signed-off-by: Abhishek Kumar --- .../src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index e4410ff9b43..393c64547ff 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -3825,7 +3825,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac // CPU and DB hotspot // FIXME: CPU & DB hotspot: listStalledVMInTransitionStateOnUpHost // FIXME: CPU & DB hotspot: listVMInTransitionStateWithRecentReportOnUpHost - // scanStalledVMInTransitionStateOnUpHost(agentId); + scanStalledVMInTransitionStateOnUpHost(agentId); processed = true; } } From 4f1eeae9f73ec6283a84c4affb1b74c7b209ac42 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 3 Sep 2024 16:25:28 +0530 Subject: [PATCH 03/62] server: DownloadListener - add caching for processConnect StartupCommand Signed-off-by: Abhishek Kumar --- .../storage/download/DownloadListener.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/com/cloud/storage/download/DownloadListener.java b/server/src/main/java/com/cloud/storage/download/DownloadListener.java index 7584a9d6403..9d094fd145a 100644 --- a/server/src/main/java/com/cloud/storage/download/DownloadListener.java +++ b/server/src/main/java/com/cloud/storage/download/DownloadListener.java @@ -21,6 +21,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Timer; +import java.util.concurrent.TimeUnit; import javax.inject.Inject; @@ -53,11 +54,14 @@ import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.agent.api.to.DataObjectType; import com.cloud.exception.ConnectionException; import com.cloud.host.Host; +import com.cloud.hypervisor.Hypervisor; import com.cloud.resource.ResourceManager; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.download.DownloadState.DownloadEvent; import com.cloud.storage.upload.UploadListener; import com.cloud.utils.exception.CloudRuntimeException; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; /** * Monitor progress of template download to a single storage server @@ -134,6 +138,8 @@ public class DownloadListener implements Listener { @Inject private VolumeService _volumeSrv; + private Cache> zoneHypervisorsCache; + // TODO: this constructor should be the one used for template only, remove other template constructor later public DownloadListener(EndPoint ssAgent, DataStore store, DataObject object, Timer timer, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, AsyncCompletionCallback callback) { @@ -149,6 +155,12 @@ public class DownloadListener implements Listener { _callback = callback; DownloadAnswer answer = new DownloadAnswer("", Status.NOT_DOWNLOADED); callback(answer); + + zoneHypervisorsCache = Caffeine.newBuilder() + .maximumSize(512) + .expireAfterWrite(30, TimeUnit.SECONDS) + .build(); + } public AsyncCompletionCallback getCallback() { @@ -271,19 +283,24 @@ public class DownloadListener implements Listener { public void processHostAdded(long hostId) { } + protected List getAvailHypervisorInZone(long zoneId) { + return _resourceMgr.listAvailHypervisorInZone(zoneId); + } + @Override public void processConnect(Host agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (cmd instanceof StartupRoutingCommand) { - /* FIXME: CPU and DB hotspot - List hypers = _resourceMgr.listAvailHypervisorInZone(agent.getDataCenterId()); - HypervisorType hostHyper = agent.getHypervisorType(); + // FIXME: CPU and DB hotspot + List hypers = zoneHypervisorsCache.get(agent.getDataCenterId(), + this::getAvailHypervisorInZone); + Hypervisor.HypervisorType hostHyper = agent.getHypervisorType(); if (hypers.contains(hostHyper)) { return; } _imageSrv.handleSysTemplateDownload(hostHyper, agent.getDataCenterId()); // update template_zone_ref for cross-zone templates _imageSrv.associateCrosszoneTemplatesToZone(agent.getDataCenterId()); - */ + } /* This can be removed else if ( cmd instanceof StartupStorageCommand) { From 060a8ca623c1602dc8fc6e582850604f5ee80c2e Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 3 Sep 2024 17:56:03 +0530 Subject: [PATCH 04/62] fix Signed-off-by: Abhishek Kumar --- .../storage/download/DownloadListener.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/server/src/main/java/com/cloud/storage/download/DownloadListener.java b/server/src/main/java/com/cloud/storage/download/DownloadListener.java index 9d094fd145a..6bf63404bfa 100644 --- a/server/src/main/java/com/cloud/storage/download/DownloadListener.java +++ b/server/src/main/java/com/cloud/storage/download/DownloadListener.java @@ -140,6 +140,13 @@ public class DownloadListener implements Listener { private Cache> zoneHypervisorsCache; + protected void initZoneHypervisorsCache() { + zoneHypervisorsCache = Caffeine.newBuilder() + .maximumSize(32) + .expireAfterWrite(30, TimeUnit.SECONDS) + .build(); + } + // TODO: this constructor should be the one used for template only, remove other template constructor later public DownloadListener(EndPoint ssAgent, DataStore store, DataObject object, Timer timer, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, AsyncCompletionCallback callback) { @@ -155,12 +162,12 @@ public class DownloadListener implements Listener { _callback = callback; DownloadAnswer answer = new DownloadAnswer("", Status.NOT_DOWNLOADED); callback(answer); + initZoneHypervisorsCache(); + } - zoneHypervisorsCache = Caffeine.newBuilder() - .maximumSize(512) - .expireAfterWrite(30, TimeUnit.SECONDS) - .build(); - + public DownloadListener(DownloadMonitorImpl monitor) { + _downloadMonitor = monitor; + initZoneHypervisorsCache(); } public AsyncCompletionCallback getCallback() { @@ -218,10 +225,6 @@ public class DownloadListener implements Listener { s_logger.log(level, message + ", " + object.getType() + ": " + object.getId() + " at host " + _ssAgent.getId()); } - public DownloadListener(DownloadMonitorImpl monitor) { - _downloadMonitor = monitor; - } - @Override public boolean isRecurring() { return false; From 8ee5e6a99aecc6cdee84a4f4e47fb74f079fe106 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 4 Sep 2024 18:35:23 +0530 Subject: [PATCH 05/62] refactor transitioning vm process report Signed-off-by: Abhishek Kumar --- .../cloud/vm/VirtualMachineManagerImpl.java | 114 ++++++------------ .../framework/jobs/dao/VmWorkJobDao.java | 1 + .../framework/jobs/dao/VmWorkJobDaoImpl.java | 16 +++ 3 files changed, 57 insertions(+), 74 deletions(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 393c64547ff..bde5a50cb06 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -48,10 +48,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import javax.persistence.EntityExistsException; -import com.cloud.configuration.Resource; -import com.cloud.event.ActionEventUtils; -import com.cloud.exception.ResourceAllocationException; -import com.google.gson.Gson; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.dao.AnnotationDao; @@ -154,6 +150,7 @@ import com.cloud.api.query.dao.UserVmJoinDao; import com.cloud.api.query.vo.DomainRouterJoinVO; import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.capacity.CapacityManager; +import com.cloud.configuration.Resource; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsVO; import com.cloud.dc.ClusterVO; @@ -171,6 +168,7 @@ import com.cloud.deploy.DeploymentPlanner; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.deploy.DeploymentPlanningManager; import com.cloud.deployasis.dao.UserVmDeployAsIsDetailsDao; +import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; import com.cloud.event.UsageEventVO; @@ -182,6 +180,7 @@ import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.OperationTimedoutException; +import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageAccessException; import com.cloud.exception.StorageUnavailableException; @@ -273,6 +272,9 @@ import com.cloud.vm.dao.VMInstanceDao; import com.cloud.vm.snapshot.VMSnapshotManager; import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import com.google.gson.Gson; public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMachineManager, VmWorkJobHandler, Listener, Configurable { private static final Logger s_logger = Logger.getLogger(VirtualMachineManagerImpl.class); @@ -393,6 +395,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac private AnnotationDao annotationDao; @Inject ResourceCleanupService resourceCleanupService; + @Inject + VmWorkJobDao vmWorkJobDao; + + private LoadingCache> vmIdsInProgressCache; VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this); @@ -805,6 +811,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Override public boolean start() { + vmIdsInProgressCache = Caffeine.newBuilder() + .expireAfterWrite(10, TimeUnit.SECONDS) + .maximumSize(1) + .build(key -> vmWorkJobDao.listVmIdsWithPendingJob()); _executor.scheduleAtFixedRate(new CleanupTask(), 5, VmJobStateReportInterval.value(), TimeUnit.SECONDS); _executor.scheduleAtFixedRate(new TransitionTask(), VmOpCleanupInterval.value(), VmOpCleanupInterval.value(), TimeUnit.SECONDS); cancelWorkItems(_nodeId); @@ -5003,25 +5013,27 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac // (which is relatively safe to do so) final long stallThresholdInMs = VmJobStateReportInterval.value() * 2; final Date cutTime = new Date(DateUtil.currentGMTTime().getTime() - stallThresholdInMs); + HostVO hostVO = _hostDao.findById(hostId); + if (!Status.Up.equals(hostVO.getStatus())) { + return; + } // FIXME: CPU & DB hotspot: listStalledVMInTransitionStateOnUpHost - final List mostLikelyStoppedVMs = listStalledVMInTransitionStateOnUpHost(hostId, cutTime); - for (final Long vmId : mostLikelyStoppedVMs) { - final VMInstanceVO vm = _vmDao.findById(vmId); - assert vm != null; + final List hostTransitionVms = _vmDao.listByHostAndState(hostId, State.Starting, State.Stopping, State.Migrating); + final List mostLikelyStoppedVMs = listStalledVMInTransitionStateOnUpHost(hostTransitionVms, cutTime.getTime()); + for (final VMInstanceVO vm : mostLikelyStoppedVMs) { handlePowerOffReportWithNoPendingJobsOnVM(vm); } // FIXME: CPU & DB hotspot: listVMInTransitionStateWithRecentReportOnUpHost - final List vmsWithRecentReport = listVMInTransitionStateWithRecentReportOnUpHost(hostId, cutTime); - for (final Long vmId : vmsWithRecentReport) { - final VMInstanceVO vm = _vmDao.findById(vmId); - assert vm != null; + final List vmsWithRecentReport = listVMInTransitionStateWithRecentReportOnUpHost(hostTransitionVms, cutTime.getTime()); + for (final VMInstanceVO vm : vmsWithRecentReport) { if (vm.getPowerState() == PowerState.PowerOn) { handlePowerOnReportWithNoPendingJobsOnVM(vm); } else { handlePowerOffReportWithNoPendingJobsOnVM(vm); } } + long elapsed = System.currentTimeMillis() - startTime; } private void scanStalledVMInTransitionStateOnDisconnectedHosts() { @@ -5036,72 +5048,26 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - private List listStalledVMInTransitionStateOnUpHost(final long hostId, final Date cutTime) { - final String sql = "SELECT i.id\n" + - "FROM vm_instance AS i\n" + - "INNER JOIN host AS h ON i.host_id = h.id\n" + - "WHERE h.status = 'UP'\n" + - " AND h.id = ?\n" + - " AND i.power_state_update_time < ?\n" + - " AND i.state IN ('Starting', 'Stopping', 'Migrating')\n" + - " AND i.id NOT IN (\n" + - " SELECT vm_instance_id\n" + - " FROM vm_work_job AS w\n" + - " INNER JOIN async_job AS j ON w.id = j.id\n" + - " WHERE j.job_status = ?\n" + - " )\n" + - " AND i.removed IS NULL"; - - final List l = new ArrayList<>(); - try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB)) { - String cutTimeStr = DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), cutTime); - - try (PreparedStatement pstmt = txn.prepareAutoCloseStatement(sql)) { - pstmt.setLong(1, hostId); - pstmt.setString(2, cutTimeStr); - pstmt.setInt(3, JobInfo.Status.IN_PROGRESS.ordinal()); - final ResultSet rs = pstmt.executeQuery(); - while (rs.next()) { - l.add(rs.getLong(1)); - } - } catch (SQLException e) { - s_logger.error(String.format("Unable to execute SQL [%s] with params {\"h.id\": %s, \"i.power_state_update_time\": \"%s\"} due to [%s].", sql, hostId, cutTimeStr, e.getMessage()), e); - } + private List listStalledVMInTransitionStateOnUpHost( + final List transitioningVms, final long cutTime) { + if (CollectionUtils.isEmpty(transitioningVms)) { + return transitioningVms; } - return l; + List vmIdsInProgress = vmIdsInProgressCache.get(0); + return transitioningVms.stream() + .filter(v -> v.getPowerStateUpdateTime().getTime() < cutTime && !vmIdsInProgress.contains(v.getId())) + .collect(Collectors.toList()); } - private List listVMInTransitionStateWithRecentReportOnUpHost(final long hostId, final Date cutTime) { - final String sql = "SELECT i.id\n" + - "FROM vm_instance AS i\n" + - "INNER JOIN host AS h ON i.host_id = h.id\n" + - "WHERE h.status = 'UP' \n" + - " AND h.id = ?\n" + - " AND i.power_state_update_time > ?\n" + - " AND i.state IN ('Starting', 'Stopping', 'Migrating')\n" + - " AND i.id NOT IN (SELECT vm_instance_id FROM vm_work_job AS w\n" + - " INNER JOIN async_job AS j ON w.id = j.id\n" + - " WHERE j.job_status = ?)\n" + - " AND i.removed IS NULL"; - - final List l = new ArrayList<>(); - try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB)) { - String cutTimeStr = DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), cutTime); - int jobStatusInProgress = JobInfo.Status.IN_PROGRESS.ordinal(); - - try (PreparedStatement pstmt = txn.prepareAutoCloseStatement(sql)) { - pstmt.setLong(1, hostId); - pstmt.setString(2, cutTimeStr); - pstmt.setInt(3, jobStatusInProgress); - final ResultSet rs = pstmt.executeQuery(); - while (rs.next()) { - l.add(rs.getLong(1)); - } - } catch (final SQLException e) { - s_logger.error(String.format("Unable to execute SQL [%s] with params {\"h.id\": %s, \"i.power_state_update_time\": \"%s\", \"j.job_status\": %s} due to [%s].", sql, hostId, cutTimeStr, jobStatusInProgress, e.getMessage()), e); - } - return l; + private List listVMInTransitionStateWithRecentReportOnUpHost( + final List transitioningVms, final long cutTime) { + if (CollectionUtils.isEmpty(transitioningVms)) { + return transitioningVms; } + List vmIdsInProgress = vmIdsInProgressCache.get(0); + return transitioningVms.stream() + .filter(v -> v.getPowerStateUpdateTime().getTime() > cutTime && !vmIdsInProgress.contains(v.getId())) + .collect(Collectors.toList()); } private List listStalledVMInTransitionStateOnDisconnectedHosts(final Date cutTime) { diff --git a/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDao.java b/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDao.java index b3bfda0334c..79ec3f2b087 100644 --- a/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDao.java +++ b/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDao.java @@ -40,4 +40,5 @@ public interface VmWorkJobDao extends GenericDao { void expungeLeftoverWorkJobs(long msid); int expungeByVmList(List vmIds, Long batchSize); + List listVmIdsWithPendingJob(); } diff --git a/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java b/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java index f78241fff49..b205d975d23 100644 --- a/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java +++ b/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java @@ -24,6 +24,7 @@ import java.util.List; import javax.annotation.PostConstruct; import javax.inject.Inject; +import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO; import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO.Step; import org.apache.cloudstack.jobs.JobInfo; @@ -33,6 +34,8 @@ import org.apache.log4j.Logger; import com.cloud.utils.DateUtil; 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.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; @@ -226,4 +229,17 @@ public class VmWorkJobDaoImpl extends GenericDaoBase implemen sc.setParameters("vmIds", vmIds.toArray()); return batchExpunge(sc, batchSize); } + + @Override + public List listVmIdsWithPendingJob() { + GenericSearchBuilder sb = createSearchBuilder(Long.class); + SearchBuilder asyncJobSearch = _baseJobDao.createSearchBuilder(); + asyncJobSearch.and("status", asyncJobSearch.entity().getStatus(), SearchCriteria.Op.EQ); + sb.join("asyncJobSearch", asyncJobSearch, sb.entity().getId(), asyncJobSearch.entity().getId(), JoinBuilder.JoinType.INNER); + sb.and("removed", sb.entity().getRemoved(), Op.NULL); + sb.selectFields(sb.entity().getVmInstanceId()); + SearchCriteria sc = sb.create(); + sc.setJoinParameters("asyncJobSearch", "status", JobInfo.Status.IN_PROGRESS); + return customSearch(sc, null); + } } From af53644a0b4051bd0e92c277e5524b942b98445e Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 5 Sep 2024 10:55:08 +0530 Subject: [PATCH 06/62] utils: add wrapper for the loading cache Follow up for #9628 Creates a utility class LazyCache which currently wraps Caffeine library Cache class. Signed-off-by: Abhishek Kumar --- .../config/impl/ConfigDepotImpl.java | 14 +-- .../cloudstack/utils/cache/LazyCache.java | 48 ++++++++ .../cloudstack/utils/cache/LazyCacheTest.java | 115 ++++++++++++++++++ 3 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 utils/src/main/java/org/apache/cloudstack/utils/cache/LazyCache.java create mode 100644 utils/src/test/java/org/apache/cloudstack/utils/cache/LazyCacheTest.java diff --git a/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java b/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java index 28ab9f0a102..fb37d4a5477 100644 --- a/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java +++ b/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java @@ -23,7 +23,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; import javax.inject.Inject; @@ -36,6 +35,7 @@ import org.apache.cloudstack.framework.config.ScopedConfigStorage; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao; import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao; +import org.apache.cloudstack.utils.cache.LazyCache; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; @@ -43,8 +43,6 @@ import org.apache.log4j.Logger; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; import com.cloud.utils.exception.CloudRuntimeException; -import com.github.benmanes.caffeine.cache.Cache; -import com.github.benmanes.caffeine.cache.Caffeine; /** * ConfigDepotImpl implements the ConfigDepot and ConfigDepotAdmin interface. @@ -86,17 +84,15 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin { List _scopedStorages; Set _configured = Collections.synchronizedSet(new HashSet()); Set newConfigs = Collections.synchronizedSet(new HashSet<>()); - Cache configCache; + LazyCache configCache; private HashMap>> _allKeys = new HashMap>>(1007); HashMap>> _scopeLevelConfigsMap = new HashMap>>(); public ConfigDepotImpl() { - configCache = Caffeine.newBuilder() - .maximumSize(512) - .expireAfterWrite(CONFIG_CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS) - .build(); + configCache = new LazyCache<>(512, + CONFIG_CACHE_EXPIRE_SECONDS, this::getConfigStringValueInternal); ConfigKey.init(this); createEmptyScopeLevelMappings(); } @@ -310,7 +306,7 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin { @Override public String getConfigStringValue(String key, ConfigKey.Scope scope, Long scopeId) { - return configCache.get(getConfigCacheKey(key, scope, scopeId), this::getConfigStringValueInternal); + return configCache.get(getConfigCacheKey(key, scope, scopeId)); } @Override diff --git a/utils/src/main/java/org/apache/cloudstack/utils/cache/LazyCache.java b/utils/src/main/java/org/apache/cloudstack/utils/cache/LazyCache.java new file mode 100644 index 00000000000..0b4c91e24b3 --- /dev/null +++ b/utils/src/main/java/org/apache/cloudstack/utils/cache/LazyCache.java @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.utils.cache; + +import java.util.concurrent.TimeUnit; +import java.util.function.Function; + +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; + +public class LazyCache { + + private final LoadingCache cache; + + public LazyCache(long maximumSize, long expireAfterWriteSeconds, Function loader) { + this.cache = Caffeine.newBuilder() + .maximumSize(maximumSize) + .expireAfterWrite(expireAfterWriteSeconds, TimeUnit.SECONDS) + .build(loader::apply); + } + + public V get(K key) { + return cache.get(key); + } + + public void invalidate(K key) { + cache.invalidate(key); + } + + public void clear() { + cache.invalidateAll(); + } +} diff --git a/utils/src/test/java/org/apache/cloudstack/utils/cache/LazyCacheTest.java b/utils/src/test/java/org/apache/cloudstack/utils/cache/LazyCacheTest.java new file mode 100644 index 00000000000..75d31b95fcc --- /dev/null +++ b/utils/src/test/java/org/apache/cloudstack/utils/cache/LazyCacheTest.java @@ -0,0 +1,115 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.utils.cache; + +import static org.junit.Assert.assertEquals; + +import java.util.function.Function; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class LazyCacheTest { + private final long expireSeconds = 1; + private final String cacheValuePrefix = "ComputedValueFor:"; + private LazyCache cache; + private Function mockLoader; + + @Before + public void setUp() { + mockLoader = Mockito.mock(Function.class); + Mockito.when(mockLoader.apply(Mockito.anyString())).thenAnswer(invocation -> cacheValuePrefix + invocation.getArgument(0)); + cache = new LazyCache<>(4, expireSeconds, mockLoader); + } + + @Test + public void testCacheMissAndLoader() { + String key = "key1"; + String value = cache.get(key); + assertEquals(cacheValuePrefix + key, value); + Mockito.verify(mockLoader).apply(key); + } + + @Test + public void testLoaderNotCalledIfPresent() { + String key = "key2"; + cache.get(key); + try { + Thread.sleep((long)(0.9 * expireSeconds * 1000)); + } catch (InterruptedException ie) { + Assert.fail(String.format("Exception occurred: %s", ie.getMessage())); + } + cache.get(key); + Mockito.verify(mockLoader, Mockito.times(1)).apply(key); + } + + @Test + public void testCacheExpiration() { + String key = "key3"; + cache.get(key); + try { + Thread.sleep((long)(1.1 * expireSeconds * 1000)); + } catch (InterruptedException ie) { + Assert.fail(String.format("Exception occurred: %s", ie.getMessage())); + } + cache.get(key); + Mockito.verify(mockLoader, Mockito.times(2)).apply(key); + } + + @Test + public void testInvalidateKey() { + String key = "key4"; + cache.get(key); + cache.invalidate(key); + cache.get(key); + Mockito.verify(mockLoader, Mockito.times(2)).apply(key); + } + + @Test + public void testClearCache() { + String key1 = "key5"; + String key2 = "key6"; + cache.get(key1); + cache.get(key2); + cache.clear(); + cache.get(key1); + Mockito.verify(mockLoader, Mockito.times(2)).apply(key1); + Mockito.verify(mockLoader, Mockito.times(1)).apply(key2); + } + + @Test + public void testMaximumSize() { + String key = "key7"; + cache.get(key); + for (int i = 0; i < 4; i++) { + cache.get(String.format("newkey-%d", i)); + } + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + Assert.fail(String.format("Exception occurred: %s", ie.getMessage())); + } + cache.get(key); + Mockito.verify(mockLoader, Mockito.times(2)).apply(key); + } +} From 8f6c657159b9424d44072f0f4cebbc434245c7e8 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 6 Sep 2024 14:27:56 +0530 Subject: [PATCH 07/62] optimize scanStalledVms procedure Signed-off-by: Abhishek Kumar --- .../com/cloud/vm/VirtualMachineManagerImpl.java | 10 ++++------ .../src/main/java/com/cloud/host/dao/HostDao.java | 2 ++ .../main/java/com/cloud/host/dao/HostDaoImpl.java | 15 +++++++++++++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index bde5a50cb06..0031e352d46 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -5012,20 +5012,19 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac // and a VM stalls for status update, we will consider them to be powered off // (which is relatively safe to do so) final long stallThresholdInMs = VmJobStateReportInterval.value() * 2; - final Date cutTime = new Date(DateUtil.currentGMTTime().getTime() - stallThresholdInMs); - HostVO hostVO = _hostDao.findById(hostId); - if (!Status.Up.equals(hostVO.getStatus())) { + final long cutTime = new Date(DateUtil.currentGMTTime().getTime() - stallThresholdInMs).getTime(); + if (!_hostDao.isHostUp(hostId)) { return; } // FIXME: CPU & DB hotspot: listStalledVMInTransitionStateOnUpHost final List hostTransitionVms = _vmDao.listByHostAndState(hostId, State.Starting, State.Stopping, State.Migrating); - final List mostLikelyStoppedVMs = listStalledVMInTransitionStateOnUpHost(hostTransitionVms, cutTime.getTime()); + final List mostLikelyStoppedVMs = listStalledVMInTransitionStateOnUpHost(hostTransitionVms, cutTime); for (final VMInstanceVO vm : mostLikelyStoppedVMs) { handlePowerOffReportWithNoPendingJobsOnVM(vm); } // FIXME: CPU & DB hotspot: listVMInTransitionStateWithRecentReportOnUpHost - final List vmsWithRecentReport = listVMInTransitionStateWithRecentReportOnUpHost(hostTransitionVms, cutTime.getTime()); + final List vmsWithRecentReport = listVMInTransitionStateWithRecentReportOnUpHost(hostTransitionVms, cutTime); for (final VMInstanceVO vm : vmsWithRecentReport) { if (vm.getPowerState() == PowerState.PowerOn) { handlePowerOnReportWithNoPendingJobsOnVM(vm); @@ -5033,7 +5032,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac handlePowerOffReportWithNoPendingJobsOnVM(vm); } } - long elapsed = System.currentTimeMillis() - startTime; } private void scanStalledVMInTransitionStateOnDisconnectedHosts() { diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java index 0022b4c4f86..b3752f0d68b 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java @@ -165,4 +165,6 @@ public interface HostDao extends GenericDao, StateDao listOrderedHostsHypervisorVersionsInDatacenter(long datacenterId, HypervisorType hypervisorType); + + boolean isHostUp(long hostId); } diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java index 084fa526323..4be6cb32ea6 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java @@ -20,6 +20,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -32,6 +33,7 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.persistence.TableGenerator; +import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Logger; import com.cloud.agent.api.VgpuTypesInfo; @@ -42,8 +44,8 @@ import com.cloud.dc.ClusterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.gpu.dao.HostGpuGroupsDao; import com.cloud.gpu.dao.VGPUTypesDao; -import com.cloud.host.Host; import com.cloud.host.DetailVO; +import com.cloud.host.Host; import com.cloud.host.Host.Type; import com.cloud.host.HostTagVO; import com.cloud.host.HostVO; @@ -70,7 +72,6 @@ import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.db.UpdateBuilder; import com.cloud.utils.exception.CloudRuntimeException; -import java.util.Arrays; @DB @TableGenerator(name = "host_req_sq", table = "op_host", pkColumnName = "id", valueColumnName = "sequence", allocationSize = 1) @@ -1510,4 +1511,14 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao } return String.format(sqlFindHostInZoneToExecuteCommand, hostResourceStatus); } + + @Override + public boolean isHostUp(long hostId) { + GenericSearchBuilder sb = createSearchBuilder(Status.class); + sb.and("id", sb.entity().getId(), Op.EQ); + sb.selectFields(sb.entity().getStatus()); + SearchCriteria sc = sb.create(); + List statuses = customSearch(sc, null); + return CollectionUtils.isNotEmpty(statuses) && Status.Up.equals(statuses.get(0)); + } } From e798ab30b35d47e68783ec48fec5fcc9d7da8a41 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 6 Sep 2024 14:28:30 +0530 Subject: [PATCH 08/62] cache api permission in DynamicRoleBasedAPIAccessChecker Signed-off-by: Abhishek Kumar --- .../acl/DynamicRoleBasedAPIAccessChecker.java | 69 ++++++++++++++++--- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java b/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java index 3f41b5fe1c5..5933a965c2c 100644 --- a/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java +++ b/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java @@ -27,6 +27,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.utils.cache.LazyCache; import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RolePermissionEntity.Permission; @@ -35,6 +36,7 @@ import com.cloud.exception.UnavailableCommandException; import com.cloud.user.Account; import com.cloud.user.AccountService; import com.cloud.user.User; +import com.cloud.utils.Pair; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.PluggableService; import org.apache.commons.lang3.StringUtils; @@ -49,6 +51,9 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API private List services; private Map> annotationRoleBasedApisMap = new HashMap>(); + final private LazyCache>> accountRolePermissionsCache; + final private LazyCache>> rolePermissionsCache; + private static final Logger LOGGER = Logger.getLogger(DynamicRoleBasedAPIAccessChecker.class.getName()); protected DynamicRoleBasedAPIAccessChecker() { @@ -56,6 +61,10 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API for (RoleType roleType : RoleType.values()) { annotationRoleBasedApisMap.put(roleType, new HashSet()); } + accountRolePermissionsCache = new LazyCache<>(32, 60, + this::getAccountRolePermissions); + rolePermissionsCache = new LazyCache<>(32, 60, + this::getRolePermissions); } @Override @@ -101,24 +110,66 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API annotationRoleBasedApisMap.get(role.getRoleType()).contains(apiName); } + protected Pair> getAccountRolePermissions(long accountId) { + LOGGER.debug("RolePermissions not available in cache for-----------------------------" + accountId); + Account account = accountService.getAccount(accountId); + if (account == null) { + return null; + } + final Role accountRole = roleService.findRole(account.getRoleId()); + if (accountRole == null || accountRole.getId() < 1L) { + return new Pair<>(null, null); + } + + if (accountRole.getRoleType() == RoleType.Admin && accountRole.getId() == RoleType.Admin.getId()) { + return new Pair<>(accountRole, null); + } + + return new Pair<>(accountRole, roleService.findAllPermissionsBy(accountRole.getId())); + } + + protected Pair> getRolePermissions(long roleId) { + LOGGER.debug("RolePermissions not available in cache for role-----------------------------" + roleId); + final Role accountRole = roleService.findRole(roleId); + if (accountRole == null || accountRole.getId() < 1L) { + return new Pair<>(null, null); + } + + if (accountRole.getRoleType() == RoleType.Admin && accountRole.getId() == RoleType.Admin.getId()) { + return new Pair<>(accountRole, null); + } + + return new Pair<>(accountRole, roleService.findAllPermissionsBy(accountRole.getId())); + } + @Override public boolean checkAccess(User user, String commandName) throws PermissionDeniedException { if (!isEnabled()) { return true; } - - // FIXME: potential hotspot, could be cached? - Account account = accountService.getAccount(user.getAccountId()); - if (account == null) { - throw new PermissionDeniedException(String.format("The account id [%s] for user id [%s] is null.", user.getAccountId(), user.getUuid())); + Pair> accountRoleAndPermissions = accountRolePermissionsCache.get(user.getAccountId()); + if (accountRoleAndPermissions == null) { + throw new PermissionDeniedException(String.format("Account for user id [%s] cannot be found", user.getUuid())); } - - return checkAccess(account, commandName); + final Role accountRole = accountRoleAndPermissions.first(); + if (accountRoleAndPermissions.first() == null) { + throw new PermissionDeniedException(String.format("Account role for user id [%s] cannot be found.", user.getUuid())); + } + if (accountRole.getRoleType() == RoleType.Admin && accountRole.getId() == RoleType.Admin.getId()) { + LOGGER.info(String.format("Account for user id [%s] is Root Admin or Domain Admin, all APIs are allowed.", user.getUuid())); + return true; + } + List allPermissions = accountRoleAndPermissions.second(); + if (checkApiPermissionByRole(accountRole, commandName, allPermissions)) { + return true; + } + throw new UnavailableCommandException(String.format("The API [%s] does not exist or is not available for the account for user id [%s].", commandName, user.getUuid())); } public boolean checkAccess(Account account, String commandName) { - final Role accountRole = roleService.findRole(account.getRoleId()); - if (accountRole == null || accountRole.getId() < 1L) { + Pair> roleAndPermissions = rolePermissionsCache.get(account.getRoleId()); + final Role accountRole = roleAndPermissions.first(); + if (accountRole == null) { throw new PermissionDeniedException(String.format("The account [%s] has role null or unknown.", account)); } From 61764aba1f7271c6fa22dc04cb10585b65b9d138 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 9 Sep 2024 19:39:50 +0530 Subject: [PATCH 09/62] cache and executors refactoring Signed-off-by: Abhishek Kumar --- .../cloud/vm/VirtualMachineManagerImpl.java | 8 +- .../cloud/capacity/CapacityManagerImpl.java | 34 ++++++-- .../storage/download/DownloadListener.java | 19 ++--- .../cloudstack/utils/cache/SingleCache.java | 48 +++++++++++ .../utils/executor/QueueExecutor.java | 82 +++++++++++++++++++ 5 files changed, 167 insertions(+), 24 deletions(-) create mode 100644 utils/src/main/java/org/apache/cloudstack/utils/cache/SingleCache.java create mode 100644 utils/src/main/java/org/apache/cloudstack/utils/executor/QueueExecutor.java diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 0031e352d46..9ce9c5948dd 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -84,6 +84,7 @@ import org.apache.cloudstack.resource.ResourceCleanupService; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.cloudstack.utils.cache.SingleCache; import org.apache.cloudstack.utils.identity.ManagementServerNode; import org.apache.cloudstack.vm.UnmanagedVMsManager; import org.apache.commons.collections.CollectionUtils; @@ -398,7 +399,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Inject VmWorkJobDao vmWorkJobDao; - private LoadingCache> vmIdsInProgressCache; + private SingleCache> vmIdsInProgressCache; VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this); @@ -811,10 +812,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Override public boolean start() { - vmIdsInProgressCache = Caffeine.newBuilder() - .expireAfterWrite(10, TimeUnit.SECONDS) - .maximumSize(1) - .build(key -> vmWorkJobDao.listVmIdsWithPendingJob()); + vmIdsInProgressCache = new SingleCache<>(10, vmWorkJobDao::listVmIdsWithPendingJob); _executor.scheduleAtFixedRate(new CleanupTask(), 5, VmJobStateReportInterval.value(), TimeUnit.SECONDS); _executor.scheduleAtFixedRate(new TransitionTask(), VmOpCleanupInterval.value(), VmOpCleanupInterval.value(), TimeUnit.SECONDS); cancelWorkItems(_nodeId); diff --git a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java index 9c5f3e0fd3b..fc70b2b2370 100644 --- a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java @@ -36,6 +36,8 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.PublishScope; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.utils.cache.LazyCache; +import org.apache.cloudstack.utils.executor.QueueExecutor; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -50,7 +52,6 @@ import com.cloud.capacity.dao.CapacityDao; import com.cloud.configuration.Config; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsVO; -import com.cloud.dc.ClusterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.deploy.DeploymentClusterPlanner; import com.cloud.event.UsageEventVO; @@ -142,6 +143,9 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, @Inject MessageBus _messageBus; + private LazyCache> clusterValuesCache; + private QueueExecutor hostCapacityUpdateExecutor; + @Override public boolean configure(String name, Map params) throws ConfigurationException { _vmCapacityReleaseInterval = NumbersUtil.parseInt(_configDao.getValue(Config.CapacitySkipcountingHours.key()), 3600); @@ -150,6 +154,9 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, _agentManager.registerForHostEvents(new StorageCapacityListener(_capacityDao, _storageMgr), true, false, false); _agentManager.registerForHostEvents(new ComputeCapacityListener(_capacityDao, this), true, false, false); + hostCapacityUpdateExecutor = new QueueExecutor<>("HostCapacityUpdateExecutor", 10, 10, + s_logger, this::updateCapacityForHostInternal); + return true; } @@ -157,11 +164,14 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, public boolean start() { _resourceMgr.registerResourceEvent(ResourceListener.EVENT_PREPARE_MAINTENANCE_AFTER, this); _resourceMgr.registerResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, this); + clusterValuesCache = new LazyCache<>(16, 60, this::getClusterValues); + hostCapacityUpdateExecutor.startProcessing(); return true; } @Override public boolean stop() { + hostCapacityUpdateExecutor.shutdown(); return true; } @@ -631,9 +641,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, return totalAllocatedSize; } - @DB - @Override - public void updateCapacityForHost(final Host host) { + protected void updateCapacityForHostInternal(final Host host) { // prepare the service offerings List offerings = _offeringsDao.listAllIncludingRemoved(); Map offeringsMap = new HashMap(); @@ -643,6 +651,17 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, updateCapacityForHost(host, offeringsMap); } + @DB + @Override + public void updateCapacityForHost(final Host host) { + hostCapacityUpdateExecutor.queueRequest(host); + } + + protected Pair getClusterValues(long clusterId) { + return new Pair<>(_clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio"), + _clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio")); + } + @DB @Override public void updateCapacityForHost(final Host host, final Map offeringsMap) { @@ -665,9 +684,10 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, } vms.addAll(vosMigrating); - ClusterVO cluster = _clusterDao.findById(host.getClusterId()); - ClusterDetailsVO clusterDetailCpu = _clusterDetailsDao.findDetail(cluster.getId(), "cpuOvercommitRatio"); - ClusterDetailsVO clusterDetailRam = _clusterDetailsDao.findDetail(cluster.getId(), "memoryOvercommitRatio"); + Pair clusterValues = + clusterValuesCache.get(host.getClusterId()); + ClusterDetailsVO clusterDetailCpu = clusterValues.first(); + ClusterDetailsVO clusterDetailRam = clusterValues.second(); Float clusterCpuOvercommitRatio = Float.parseFloat(clusterDetailCpu.getValue()); Float clusterRamOvercommitRatio = Float.parseFloat(clusterDetailRam.getValue()); for (VMInstanceVO vm : vms) { diff --git a/server/src/main/java/com/cloud/storage/download/DownloadListener.java b/server/src/main/java/com/cloud/storage/download/DownloadListener.java index 6bf63404bfa..4d1dcdcae40 100644 --- a/server/src/main/java/com/cloud/storage/download/DownloadListener.java +++ b/server/src/main/java/com/cloud/storage/download/DownloadListener.java @@ -25,6 +25,8 @@ import java.util.concurrent.TimeUnit; import javax.inject.Inject; +import org.apache.cloudstack.utils.cache.LazyCache; +import org.apache.cloudstack.utils.cache.SingleCache; import org.apache.log4j.Level; import org.apache.log4j.Logger; @@ -138,13 +140,11 @@ public class DownloadListener implements Listener { @Inject private VolumeService _volumeSrv; - private Cache> zoneHypervisorsCache; + private LazyCache> zoneHypervisorsCache; protected void initZoneHypervisorsCache() { - zoneHypervisorsCache = Caffeine.newBuilder() - .maximumSize(32) - .expireAfterWrite(30, TimeUnit.SECONDS) - .build(); + zoneHypervisorsCache = + new LazyCache<>(32, 30, _resourceMgr::listAvailHypervisorInZone); } // TODO: this constructor should be the one used for template only, remove other template constructor later @@ -286,18 +286,13 @@ public class DownloadListener implements Listener { public void processHostAdded(long hostId) { } - protected List getAvailHypervisorInZone(long zoneId) { - return _resourceMgr.listAvailHypervisorInZone(zoneId); - } - @Override public void processConnect(Host agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (cmd instanceof StartupRoutingCommand) { // FIXME: CPU and DB hotspot - List hypers = zoneHypervisorsCache.get(agent.getDataCenterId(), - this::getAvailHypervisorInZone); + List hypervisors = zoneHypervisorsCache.get(agent.getDataCenterId()); Hypervisor.HypervisorType hostHyper = agent.getHypervisorType(); - if (hypers.contains(hostHyper)) { + if (hypervisors.contains(hostHyper)) { return; } _imageSrv.handleSysTemplateDownload(hostHyper, agent.getDataCenterId()); diff --git a/utils/src/main/java/org/apache/cloudstack/utils/cache/SingleCache.java b/utils/src/main/java/org/apache/cloudstack/utils/cache/SingleCache.java new file mode 100644 index 00000000000..4302a5258c8 --- /dev/null +++ b/utils/src/main/java/org/apache/cloudstack/utils/cache/SingleCache.java @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.utils.cache; + +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; + +public class SingleCache { + + private final LoadingCache cache; + + public SingleCache(long expireAfterWriteSeconds, Supplier loader) { + this.cache = Caffeine.newBuilder() + .maximumSize(1) + .expireAfterWrite(expireAfterWriteSeconds, TimeUnit.SECONDS) + .build(key -> loader.get()); + } + + public V get() { + return cache.get(null); + } + + public void invalidate() { + cache.invalidate(null); + } + + public void clear() { + cache.invalidateAll(); + } +} diff --git a/utils/src/main/java/org/apache/cloudstack/utils/executor/QueueExecutor.java b/utils/src/main/java/org/apache/cloudstack/utils/executor/QueueExecutor.java new file mode 100644 index 00000000000..589acc4976b --- /dev/null +++ b/utils/src/main/java/org/apache/cloudstack/utils/executor/QueueExecutor.java @@ -0,0 +1,82 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.utils.executor; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import org.apache.log4j.Logger; + +public class QueueExecutor { + + private final String name; + private final int processingSize; + private final int processingInterval; + private final BlockingQueue requestQueue; + private final ScheduledExecutorService executorService; + private final Logger logger; + private final Consumer consumer; + + public QueueExecutor(String name, int processingSize, int processingInterval, Logger logger, + Consumer consumer) { + this.name = name; + this.processingSize = processingSize; + this.processingInterval = processingInterval; + this.logger = logger; + this.consumer = consumer; + requestQueue = new LinkedBlockingQueue<>(processingSize); + executorService = Executors.newSingleThreadScheduledExecutor(); + } + + public void queueRequest(K request) { + try { + requestQueue.put(request); + if (requestQueue.size() >= processingSize) { + processRequests(); + } + } catch (InterruptedException e) { + logger.warn(String.format("Error queuing request for %s", name), e); + } + } + + public void startProcessing() { + executorService.scheduleAtFixedRate(this::processRequests, 0, + processingInterval, TimeUnit.SECONDS); + } + + private void processRequests() { + List requestsToProcess = new ArrayList<>(); + requestQueue.drainTo(requestsToProcess, processingSize); + + if (!requestsToProcess.isEmpty()) { + for (K request : requestsToProcess) { + consumer.accept(request); + } + } + } + + public void shutdown() { + executorService.shutdown(); + } +} From df137fc38762062a24f989c0af765936eca03edd Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 10 Sep 2024 10:22:59 +0530 Subject: [PATCH 10/62] refactor Signed-off-by: Abhishek Kumar --- .../com/cloud/capacity/CapacityManager.java | 5 -- .../com/cloud/alert/AlertManagerImpl.java | 12 +--- .../cloud/capacity/CapacityManagerImpl.java | 56 +++++++++++++------ .../storage/download/DownloadListener.java | 22 ++++---- .../cloudstack/utils/cache/SingleCache.java | 6 +- ...QueueExecutor.java => QueuedExecutor.java} | 10 ++-- 6 files changed, 60 insertions(+), 51 deletions(-) rename utils/src/main/java/org/apache/cloudstack/utils/executor/{QueueExecutor.java => QueuedExecutor.java} (88%) diff --git a/engine/components-api/src/main/java/com/cloud/capacity/CapacityManager.java b/engine/components-api/src/main/java/com/cloud/capacity/CapacityManager.java index 1c3edad886b..0f35fbe977e 100644 --- a/engine/components-api/src/main/java/com/cloud/capacity/CapacityManager.java +++ b/engine/components-api/src/main/java/com/cloud/capacity/CapacityManager.java @@ -16,14 +16,11 @@ // under the License. package com.cloud.capacity; -import java.util.Map; - import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import com.cloud.host.Host; import com.cloud.offering.ServiceOffering; -import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.VMTemplateVO; import com.cloud.utils.Pair; import com.cloud.vm.VirtualMachine; @@ -133,8 +130,6 @@ public interface CapacityManager { void updateCapacityForHost(Host host); - void updateCapacityForHost(Host host, Map offeringsMap); - /** * @param pool storage pool * @param templateForVmCreation template that will be used for vm creation diff --git a/server/src/main/java/com/cloud/alert/AlertManagerImpl.java b/server/src/main/java/com/cloud/alert/AlertManagerImpl.java index ca26de5cf21..6c7d048894c 100644 --- a/server/src/main/java/com/cloud/alert/AlertManagerImpl.java +++ b/server/src/main/java/com/cloud/alert/AlertManagerImpl.java @@ -75,8 +75,6 @@ import com.cloud.network.Ipv6Service; import com.cloud.network.dao.IPAddressDao; import com.cloud.org.Grouping.AllocationState; import com.cloud.resource.ResourceManager; -import com.cloud.service.ServiceOfferingVO; -import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.StorageManager; import com.cloud.utils.Pair; import com.cloud.utils.component.ManagerBase; @@ -120,8 +118,6 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi @Inject protected ConfigDepot _configDepot; @Inject - ServiceOfferingDao _offeringsDao; - @Inject Ipv6Service ipv6Service; private Timer _timer = null; @@ -276,14 +272,8 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi // get all hosts...even if they are not in 'UP' state List hosts = _resourceMgr.listAllNotInMaintenanceHostsInOneZone(Host.Type.Routing, null); if (hosts != null) { - // prepare the service offerings - List offerings = _offeringsDao.listAllIncludingRemoved(); - Map offeringsMap = new HashMap(); - for (ServiceOfferingVO offering : offerings) { - offeringsMap.put(offering.getId(), offering); - } for (HostVO host : hosts) { - _capacityMgr.updateCapacityForHost(host, offeringsMap); + _capacityMgr.updateCapacityForHost(host); } } if (logger.isDebugEnabled()) { diff --git a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java index fc70b2b2370..abb67e7e714 100644 --- a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java @@ -22,6 +22,7 @@ import java.net.URI; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; @@ -37,7 +38,9 @@ import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.PublishScope; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.utils.cache.LazyCache; -import org.apache.cloudstack.utils.executor.QueueExecutor; +import org.apache.cloudstack.utils.cache.SingleCache; +import org.apache.cloudstack.utils.executor.QueuedExecutor; +import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -144,7 +147,8 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, MessageBus _messageBus; private LazyCache> clusterValuesCache; - private QueueExecutor hostCapacityUpdateExecutor; + private SingleCache> serviceOfferingsCache; + private QueuedExecutor hostCapacityUpdateExecutor; @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -154,8 +158,8 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, _agentManager.registerForHostEvents(new StorageCapacityListener(_capacityDao, _storageMgr), true, false, false); _agentManager.registerForHostEvents(new ComputeCapacityListener(_capacityDao, this), true, false, false); - hostCapacityUpdateExecutor = new QueueExecutor<>("HostCapacityUpdateExecutor", 10, 10, - s_logger, this::updateCapacityForHostInternal); + hostCapacityUpdateExecutor = new QueuedExecutor<>("HostCapacityUpdateExecutor", 10, 10, + 1, s_logger, this::updateCapacityForHostInternal); return true; } @@ -165,6 +169,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, _resourceMgr.registerResourceEvent(ResourceListener.EVENT_PREPARE_MAINTENANCE_AFTER, this); _resourceMgr.registerResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, this); clusterValuesCache = new LazyCache<>(16, 60, this::getClusterValues); + serviceOfferingsCache = new SingleCache<>(60, this::getServiceOfferingsMap); hostCapacityUpdateExecutor.startProcessing(); return true; } @@ -641,16 +646,6 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, return totalAllocatedSize; } - protected void updateCapacityForHostInternal(final Host host) { - // prepare the service offerings - List offerings = _offeringsDao.listAllIncludingRemoved(); - Map offeringsMap = new HashMap(); - for (ServiceOfferingVO offering : offerings) { - offeringsMap.put(offering.getId(), offering); - } - updateCapacityForHost(host, offeringsMap); - } - @DB @Override public void updateCapacityForHost(final Host host) { @@ -662,9 +657,33 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, _clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio")); } + + protected Map getServiceOfferingsMap() { + List serviceOfferings = _offeringsDao.listAllIncludingRemoved(); + if (CollectionUtils.isEmpty(serviceOfferings)) { + return new HashMap<>(); + } + return serviceOfferings.stream() + .collect(Collectors.toMap( + ServiceOfferingVO::getId, + offering -> offering + )); + } + + protected ServiceOfferingVO getServiceOffering(long id) { + Map map = serviceOfferingsCache.get(); + if (map.containsKey(id)) { + return map.get(id); + } + ServiceOfferingVO serviceOfferingVO = _offeringsDao.findByIdIncludingRemoved(id); + if (serviceOfferingVO != null) { + serviceOfferingsCache.invalidate(); + } + return serviceOfferingVO; + } + @DB - @Override - public void updateCapacityForHost(final Host host, final Map offeringsMap) { + protected void updateCapacityForHostInternal(final Host host) { long usedCpuCore = 0; long reservedCpuCore = 0; long usedCpu = 0; @@ -699,7 +718,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, // if vmDetailCpu or vmDetailRam is not null it means it is running in a overcommitted cluster. cpuOvercommitRatio = (vmDetailCpu != null) ? Float.parseFloat(vmDetailCpu) : clusterCpuOvercommitRatio; ramOvercommitRatio = (vmDetailRam != null) ? Float.parseFloat(vmDetailRam) : clusterRamOvercommitRatio; - ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId()); + ServiceOffering so = getServiceOffering(vm.getServiceOfferingId()); if (so == null) { so = _offeringsDao.findByIdIncludingRemoved(vm.getServiceOfferingId()); } @@ -728,6 +747,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, if (s_logger.isDebugEnabled()) { s_logger.debug("Found " + vmsByLastHostId.size() + " VM, not running on host " + host.getId()); } + for (VMInstanceVO vm : vmsByLastHostId) { Float cpuOvercommitRatio = 1.0f; Float ramOvercommitRatio = 1.0f; @@ -740,7 +760,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, cpuOvercommitRatio = Float.parseFloat(vmDetailCpu.getValue()); ramOvercommitRatio = Float.parseFloat(vmDetailRam.getValue()); } - ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId()); + ServiceOffering so = getServiceOffering(vm.getServiceOfferingId()); Map vmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId()); if (so == null) { so = _offeringsDao.findByIdIncludingRemoved(vm.getServiceOfferingId()); diff --git a/server/src/main/java/com/cloud/storage/download/DownloadListener.java b/server/src/main/java/com/cloud/storage/download/DownloadListener.java index 4d1dcdcae40..96796d01c28 100644 --- a/server/src/main/java/com/cloud/storage/download/DownloadListener.java +++ b/server/src/main/java/com/cloud/storage/download/DownloadListener.java @@ -16,20 +16,15 @@ // under the License. package com.cloud.storage.download; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Timer; -import java.util.concurrent.TimeUnit; import javax.inject.Inject; -import org.apache.cloudstack.utils.cache.LazyCache; -import org.apache.cloudstack.utils.cache.SingleCache; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; - import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; @@ -43,6 +38,9 @@ import org.apache.cloudstack.storage.command.DownloadCommand; import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import org.apache.cloudstack.storage.command.DownloadProgressCommand; import org.apache.cloudstack.storage.command.DownloadProgressCommand.RequestType; +import org.apache.cloudstack.utils.cache.LazyCache; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; import com.cloud.agent.Listener; import com.cloud.agent.api.AgentControlAnswer; @@ -62,8 +60,6 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.download.DownloadState.DownloadEvent; import com.cloud.storage.upload.UploadListener; import com.cloud.utils.exception.CloudRuntimeException; -import com.github.benmanes.caffeine.cache.Cache; -import com.github.benmanes.caffeine.cache.Caffeine; /** * Monitor progress of template download to a single storage server @@ -142,9 +138,16 @@ public class DownloadListener implements Listener { private LazyCache> zoneHypervisorsCache; + private List listAvailHypervisorInZone(long zoneId) { + if (_resourceMgr == null) { + return Collections.emptyList(); + } + return _resourceMgr.listAvailHypervisorInZone(zoneId); + } + protected void initZoneHypervisorsCache() { zoneHypervisorsCache = - new LazyCache<>(32, 30, _resourceMgr::listAvailHypervisorInZone); + new LazyCache<>(32, 30, this::listAvailHypervisorInZone); } // TODO: this constructor should be the one used for template only, remove other template constructor later @@ -289,7 +292,6 @@ public class DownloadListener implements Listener { @Override public void processConnect(Host agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (cmd instanceof StartupRoutingCommand) { - // FIXME: CPU and DB hotspot List hypervisors = zoneHypervisorsCache.get(agent.getDataCenterId()); Hypervisor.HypervisorType hostHyper = agent.getHypervisorType(); if (hypervisors.contains(hostHyper)) { diff --git a/utils/src/main/java/org/apache/cloudstack/utils/cache/SingleCache.java b/utils/src/main/java/org/apache/cloudstack/utils/cache/SingleCache.java index 4302a5258c8..5fa77d9a28c 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/cache/SingleCache.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/cache/SingleCache.java @@ -25,7 +25,7 @@ import com.github.benmanes.caffeine.cache.LoadingCache; public class SingleCache { - private final LoadingCache cache; + private final LoadingCache cache; public SingleCache(long expireAfterWriteSeconds, Supplier loader) { this.cache = Caffeine.newBuilder() @@ -35,11 +35,11 @@ public class SingleCache { } public V get() { - return cache.get(null); + return cache.get(0); } public void invalidate() { - cache.invalidate(null); + cache.invalidate(0); } public void clear() { diff --git a/utils/src/main/java/org/apache/cloudstack/utils/executor/QueueExecutor.java b/utils/src/main/java/org/apache/cloudstack/utils/executor/QueuedExecutor.java similarity index 88% rename from utils/src/main/java/org/apache/cloudstack/utils/executor/QueueExecutor.java rename to utils/src/main/java/org/apache/cloudstack/utils/executor/QueuedExecutor.java index 589acc4976b..3181f791bce 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/executor/QueueExecutor.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/executor/QueuedExecutor.java @@ -28,7 +28,9 @@ import java.util.function.Consumer; import org.apache.log4j.Logger; -public class QueueExecutor { +import com.cloud.utils.concurrency.NamedThreadFactory; + +public class QueuedExecutor { private final String name; private final int processingSize; @@ -38,15 +40,15 @@ public class QueueExecutor { private final Logger logger; private final Consumer consumer; - public QueueExecutor(String name, int processingSize, int processingInterval, Logger logger, - Consumer consumer) { + public QueuedExecutor(String name, int processingSize, int processingInterval, int maxThreads, Logger logger, + Consumer consumer) { this.name = name; this.processingSize = processingSize; this.processingInterval = processingInterval; this.logger = logger; this.consumer = consumer; requestQueue = new LinkedBlockingQueue<>(processingSize); - executorService = Executors.newSingleThreadScheduledExecutor(); + executorService = Executors.newScheduledThreadPool(maxThreads, new NamedThreadFactory(name)); } public void queueRequest(K request) { From 3e098b87a968d2be866f5ff0571f9ddcad0a1198 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 10 Sep 2024 15:22:02 +0530 Subject: [PATCH 11/62] fix Signed-off-by: Abhishek Kumar --- .../src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 9ce9c5948dd..7bfc4c4a4b9 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -5049,7 +5049,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (CollectionUtils.isEmpty(transitioningVms)) { return transitioningVms; } - List vmIdsInProgress = vmIdsInProgressCache.get(0); + List vmIdsInProgress = vmIdsInProgressCache.get(); return transitioningVms.stream() .filter(v -> v.getPowerStateUpdateTime().getTime() < cutTime && !vmIdsInProgress.contains(v.getId())) .collect(Collectors.toList()); @@ -5060,7 +5060,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (CollectionUtils.isEmpty(transitioningVms)) { return transitioningVms; } - List vmIdsInProgress = vmIdsInProgressCache.get(0); + List vmIdsInProgress = vmIdsInProgressCache.get(); return transitioningVms.stream() .filter(v -> v.getPowerStateUpdateTime().getTime() > cutTime && !vmIdsInProgress.contains(v.getId())) .collect(Collectors.toList()); From 9074c4b6ad94838d935ca1f542172150b302f8fb Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 10 Sep 2024 15:22:16 +0530 Subject: [PATCH 12/62] address process vm power state report for transitioning VMs Signed-off-by: Abhishek Kumar --- .../com/cloud/vm/VirtualMachineManager.java | 3 +++ .../com/cloud/vm/VirtualMachineManagerImpl.java | 17 +++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java b/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java index 04ba9a483e1..fc2afd65cd7 100644 --- a/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java +++ b/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java @@ -87,6 +87,9 @@ public interface VirtualMachineManager extends Manager { ConfigKey MetadataCustomCloudName = new ConfigKey<>("Advanced", String.class, "metadata.custom.cloud.name", "", "If provided, a custom cloud-name in cloud-init metadata", true, ConfigKey.Scope.Zone); + ConfigKey VmSyncPowerStateTransitioning = new ConfigKey<>("Advanced", Boolean.class, "vm.sync.power.state.transitioning", "false", + "Whether to sync power states of the transitioning and stalled VMs while processing VM power reports.", false); + interface Topics { String VM_POWER_STATE = "vm.powerstate"; } diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 7bfc4c4a4b9..748212aeba6 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -444,6 +444,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac Long.class, "systemvm.root.disk.size", "-1", "Size of root volume (in GB) of system VMs and virtual routers", true); + private boolean syncTransitioningVmPowerState; + ScheduledExecutorService _executor = null; private long _nodeId; @@ -840,6 +842,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac _messageBus.subscribe(VirtualMachineManager.Topics.VM_POWER_STATE, MessageDispatcher.getDispatcher(this)); + syncTransitioningVmPowerState = Boolean.TRUE.equals(VmSyncPowerStateTransitioning.value()); + return true; } @@ -3829,11 +3833,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (ping.getHostVmStateReport() != null) { _syncMgr.processHostVmStatePingReport(agentId, ping.getHostVmStateReport(), ping.getOutOfBand()); } - - // CPU and DB hotspot - // FIXME: CPU & DB hotspot: listStalledVMInTransitionStateOnUpHost - // FIXME: CPU & DB hotspot: listVMInTransitionStateWithRecentReportOnUpHost - scanStalledVMInTransitionStateOnUpHost(agentId); + scanStalledVMInTransitionStateOnUpHost(agentId); processed = true; } } @@ -4803,7 +4803,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac VmOpLockStateRetry, VmOpWaitInterval, ExecuteInSequence, VmJobCheckInterval, VmJobTimeout, VmJobStateReportInterval, VmConfigDriveLabel, VmConfigDriveOnPrimaryPool, VmConfigDriveForceHostCacheUse, VmConfigDriveUseHostCacheOnUnsupportedPool, HaVmRestartHostUp, ResourceCountRunningVMsonly, AllowExposeHypervisorHostname, AllowExposeHypervisorHostnameAccountLevel, SystemVmRootDiskSize, - AllowExposeDomainInMetadata, MetadataCustomCloudName + AllowExposeDomainInMetadata, MetadataCustomCloudName, VmSyncPowerStateTransitioning }; } @@ -4995,6 +4995,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } private void scanStalledVMInTransitionStateOnUpHost(final long hostId) { + if (!syncTransitioningVmPowerState) { + return; + } // Check VM that is stuck in Starting, Stopping, Migrating states, we won't check // VMs in expunging state (this need to be handled specially) // @@ -5014,14 +5017,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (!_hostDao.isHostUp(hostId)) { return; } - // FIXME: CPU & DB hotspot: listStalledVMInTransitionStateOnUpHost final List hostTransitionVms = _vmDao.listByHostAndState(hostId, State.Starting, State.Stopping, State.Migrating); final List mostLikelyStoppedVMs = listStalledVMInTransitionStateOnUpHost(hostTransitionVms, cutTime); for (final VMInstanceVO vm : mostLikelyStoppedVMs) { handlePowerOffReportWithNoPendingJobsOnVM(vm); } - // FIXME: CPU & DB hotspot: listVMInTransitionStateWithRecentReportOnUpHost final List vmsWithRecentReport = listVMInTransitionStateWithRecentReportOnUpHost(hostTransitionVms, cutTime); for (final VMInstanceVO vm : vmsWithRecentReport) { if (vm.getPowerState() == PowerState.PowerOn) { From de60fb64e844879ee5d2e2eca9073dfc787bf79d Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 10 Sep 2024 15:35:14 +0530 Subject: [PATCH 13/62] fix Signed-off-by: Abhishek Kumar --- .../src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 748212aeba6..ef59db3af86 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -5077,7 +5077,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac " AND i.id NOT IN (SELECT vm_instance_id FROM vm_work_job AS w\n" + " INNER JOIN async_job AS j ON w.id = j.id\n" + " WHERE j.job_status = ?)\n" + - " AND i.removed IS NUL"; + " AND i.removed IS NULL"; final List l = new ArrayList<>(); try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB)) { From d5a774c736145f840533b7085db4bbb102d5a99b Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 11 Sep 2024 11:44:48 +0530 Subject: [PATCH 14/62] import fix Signed-off-by: Abhishek Kumar --- .../src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index ef59db3af86..494a74ef826 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -273,8 +273,6 @@ import com.cloud.vm.dao.VMInstanceDao; import com.cloud.vm.snapshot.VMSnapshotManager; import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; -import com.github.benmanes.caffeine.cache.Caffeine; -import com.github.benmanes.caffeine.cache.LoadingCache; import com.google.gson.Gson; public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMachineManager, VmWorkJobHandler, Listener, Configurable { From 1d116057878d7aa1fba8938c5b3457ac0ce31ca9 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 11 Sep 2024 13:27:17 +0530 Subject: [PATCH 15/62] remove todo as configkey caching is implemented Signed-off-by: Abhishek Kumar --- server/src/main/java/com/cloud/api/ApiServer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/src/main/java/com/cloud/api/ApiServer.java b/server/src/main/java/com/cloud/api/ApiServer.java index cc12719c5b6..cf0e689ed27 100644 --- a/server/src/main/java/com/cloud/api/ApiServer.java +++ b/server/src/main/java/com/cloud/api/ApiServer.java @@ -1236,8 +1236,6 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer throw new PermissionDeniedException("User is null for role based API access check for command" + commandName); } - // FIXME: ConfigKey causes hotspot + connection leaks - // TODO: Implement LRU caching here... final Account account = accountMgr.getAccount(user.getAccountId()); final String accessAllowedCidrs = ApiServiceConfiguration.ApiAllowedSourceCidrList.valueIn(account.getId()).replaceAll("\\s",""); final Boolean apiSourceCidrChecksEnabled = ApiServiceConfiguration.ApiSourceCidrChecksEnabled.value(); From 68bab20d2491bba746151c14f8775ee3e62fe93c Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 12 Sep 2024 15:47:00 +0530 Subject: [PATCH 16/62] VMInstanceDao.updatePowerState refactor Signed-off-by: Abhishek Kumar --- .../com/cloud/vm/dao/VMInstanceDaoImpl.java | 57 +++++++++---------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java index 0c70f3bcd48..b85ec931e24 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -911,37 +911,34 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem @Override public boolean updatePowerState(final long instanceId, final long powerHostId, final VirtualMachine.PowerState powerState, Date wisdomEra) { - return Transaction.execute(new TransactionCallback<>() { - @Override - public Boolean doInTransaction(TransactionStatus status) { - boolean needToUpdate = false; - VMInstanceVO instance = findById(instanceId); - if (instance != null - && (null == instance.getPowerStateUpdateTime() - || instance.getPowerStateUpdateTime().before(wisdomEra))) { - Long savedPowerHostId = instance.getPowerHostId(); - if (instance.getPowerState() != powerState - || savedPowerHostId == null - || savedPowerHostId != powerHostId - || !isPowerStateInSyncWithInstanceState(powerState, powerHostId, instance)) { - instance.setPowerState(powerState); - instance.setPowerHostId(powerHostId); - instance.setPowerStateUpdateCount(1); - instance.setPowerStateUpdateTime(DateUtil.currentGMTTime()); - needToUpdate = true; - update(instanceId, instance); - } else { - // to reduce DB updates, consecutive same state update for more than 3 times - if (instance.getPowerStateUpdateCount() < MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT) { - instance.setPowerStateUpdateCount(instance.getPowerStateUpdateCount() + 1); - instance.setPowerStateUpdateTime(DateUtil.currentGMTTime()); - needToUpdate = true; - update(instanceId, instance); - } - } - } - return needToUpdate; + return Transaction.execute((TransactionCallback) status -> { + VMInstanceVO instance = findById(instanceId); + if (instance == null) { + return false; } + // Check if we need to update based on powerStateUpdateTime + if (instance.getPowerStateUpdateTime() == null || instance.getPowerStateUpdateTime().before(wisdomEra)) { + Long savedPowerHostId = instance.getPowerHostId(); + boolean isStateMismatch = instance.getPowerState() != powerState + || savedPowerHostId == null + || !savedPowerHostId.equals(powerHostId) + || !isPowerStateInSyncWithInstanceState(powerState, powerHostId, instance); + + if (isStateMismatch) { + instance.setPowerState(powerState); + instance.setPowerHostId(powerHostId); + instance.setPowerStateUpdateCount(1); + } else if (instance.getPowerStateUpdateCount() < MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT) { + instance.setPowerStateUpdateCount(instance.getPowerStateUpdateCount() + 1); + } else { + // No need to update if power state is already in sync and count exceeded + return false; + } + instance.setPowerStateUpdateTime(DateUtil.currentGMTTime()); + update(instanceId, instance); + return true; // Return true since an update occurred + } + return false; }); } From a78a2508e955fa8c08b62e56c3440ca58bad3e77 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 12 Sep 2024 16:00:17 +0530 Subject: [PATCH 17/62] server: refactor MS list retrieval for agent connect During agent join and while changing configs - host and indirect.agent.lb.algorithm, optimize calling DB for zone's host list Signed-off-by: Abhishek Kumar --- .../cloud/vm/VirtualMachineManagerImpl.java | 2 +- .../java/com/cloud/dc/dao/ClusterDao.java | 2 +- .../java/com/cloud/dc/dao/ClusterDaoImpl.java | 2 +- .../deploy/DeploymentPlanningManagerImpl.java | 2 +- .../agent/lb/IndirectAgentLBServiceImpl.java | 189 +++++++++++------- 5 files changed, 116 insertions(+), 81 deletions(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 494a74ef826..a56d3205c20 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -3530,7 +3530,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (MIGRATE_VM_ACROSS_CLUSTERS.valueIn(host.getDataCenterId()) && (HypervisorType.VMware.equals(host.getHypervisorType()) || !checkIfVmHasClusterWideVolumes(vm.getId()))) { s_logger.info("Searching for hosts in the zone for vm migration"); - List clustersToExclude = _clusterDao.listAllClusters(host.getDataCenterId()); + List clustersToExclude = _clusterDao.listAllClusterIds(host.getDataCenterId()); List clusterList = _clusterDao.listByDcHyType(host.getDataCenterId(), host.getHypervisorType().toString()); for (ClusterVO cluster : clusterList) { clustersToExclude.remove(cluster.getId()); diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java index 884b184aad5..1f31734f355 100644 --- a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java +++ b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java @@ -51,7 +51,7 @@ public interface ClusterDao extends GenericDao { List listClustersByDcId(long zoneId); - List listAllClusters(Long zoneId); + List listAllClusterIds(Long zoneId); boolean getSupportsResigning(long clusterId); } diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java index 07b79e84403..4632d168c50 100644 --- a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java @@ -283,7 +283,7 @@ public class ClusterDaoImpl extends GenericDaoBase implements C } @Override - public List listAllClusters(Long zoneId) { + public List listAllClusterIds(Long zoneId) { SearchCriteria sc = ClusterIdSearch.create(); if (zoneId != null) { sc.setParameters("dataCenterId", zoneId); diff --git a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java index 08b514fda6d..a86bdd0fea6 100644 --- a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -766,7 +766,7 @@ StateListener, Configurable { List allDedicatedPods = _dedicatedDao.listAllPods(); allPodsInDc.retainAll(allDedicatedPods); - List allClustersInDc = _clusterDao.listAllClusters(dc.getId()); + List allClustersInDc = _clusterDao.listAllClusterIds(dc.getId()); List allDedicatedClusters = _dedicatedDao.listAllClusters(); allClustersInDc.retainAll(allDedicatedClusters); diff --git a/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java b/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java index 1414a94907e..0da5f193eef 100644 --- a/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java +++ b/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java @@ -18,9 +18,7 @@ package org.apache.cloudstack.agent.lb; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; -import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -34,18 +32,22 @@ import org.apache.cloudstack.agent.lb.algorithm.IndirectAgentLBStaticAlgorithm; import org.apache.cloudstack.config.ApiServiceConfiguration; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; -import com.cloud.hypervisor.Hypervisor; import com.cloud.resource.ResourceState; import com.cloud.utils.component.ComponentLifecycleBase; +import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.exception.CloudRuntimeException; -import org.apache.commons.lang3.StringUtils; public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implements IndirectAgentLB, Configurable { public static final Logger LOG = Logger.getLogger(IndirectAgentLBServiceImpl.class); @@ -62,6 +64,10 @@ public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implement private static Map algorithmMap = new HashMap<>(); + @Inject + private DataCenterDao dataCenterDao; + @Inject + private ClusterDao clusterDao; @Inject private HostDao hostDao; @Inject @@ -78,6 +84,10 @@ public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implement throw new CloudRuntimeException(String.format("No management server addresses are defined in '%s' setting", ApiServiceConfiguration.ManagementServerAddresses.key())); } + final List msList = Arrays.asList(msServerAddresses.replace(" ", "").split(",")); + if (msList.size() == 1) { + return msList; + } List hostIdList = orderedHostIdList; if (hostIdList == null) { @@ -93,7 +103,6 @@ public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implement } final org.apache.cloudstack.agent.lb.IndirectAgentLBAlgorithm algorithm = getAgentMSLBAlgorithm(); - final List msList = Arrays.asList(msServerAddresses.replace(" ", "").split(",")); return algorithm.sort(msList, hostIdList, hostId); } @@ -121,76 +130,92 @@ public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implement } List getOrderedHostIdList(final Long dcId) { - final List hostIdList = new ArrayList<>(); - for (final Host host : getAllAgentBasedHosts()) { - if (host.getDataCenterId() == dcId) { - hostIdList.add(host.getId()); - } - } - Collections.sort(hostIdList, new Comparator() { - @Override - public int compare(Long x, Long y) { - return Long.compare(x,y); - } - }); + final List hostIdList = getAllAgentBasedHostsFromDB(dcId, null); + hostIdList.sort(Comparator.comparingLong(x -> x)); return hostIdList; } - private List getAllAgentBasedHosts() { - final List allHosts = hostDao.listAll(); - if (allHosts == null) { - return new ArrayList<>(); - } - final List agentBasedHosts = new ArrayList<>(); - for (final Host host : allHosts) { - conditionallyAddHost(agentBasedHosts, host); - } - return agentBasedHosts; - } +// private List getAllAgentBasedHosts() { +// final List allHosts = hostDao.listAll(); +// if (allHosts == null) { +// return new ArrayList<>(); +// } +// final List agentBasedHosts = new ArrayList<>(); +// for (final Host host : allHosts) { +// conditionallyAddHost(agentBasedHosts, host); +// } +// return agentBasedHosts; +// } +// +// private void conditionallyAddHost(List agentBasedHosts, Host host) { +// if (host == null) { +// if (LOG.isTraceEnabled()) { +// LOG.trace("trying to add no host to a list"); +// } +// return; +// } +// +// EnumSet allowedStates = EnumSet.of( +// ResourceState.Enabled, +// ResourceState.Maintenance, +// ResourceState.Disabled, +// ResourceState.ErrorInMaintenance, +// ResourceState.PrepareForMaintenance); +// // so the remaining EnumSet disallowedStates = EnumSet.complementOf(allowedStates) +// // would be {ResourceState.Creating, ResourceState.Error}; +// if (!allowedStates.contains(host.getResourceState())) { +// if (LOG.isTraceEnabled()) { +// LOG.trace(String.format("host is in '%s' state, not adding to the host list, (id = %s)", host.getResourceState(), host.getUuid())); +// } +// return; +// } +// +// if (host.getType() != Host.Type.Routing +// && host.getType() != Host.Type.ConsoleProxy +// && host.getType() != Host.Type.SecondaryStorage +// && host.getType() != Host.Type.SecondaryStorageVM) { +// if (LOG.isTraceEnabled()) { +// LOG.trace(String.format("host is of wrong type, not adding to the host list, (id = %s, type = %s)", host.getUuid(), host.getType())); +// } +// return; +// } +// +// if (host.getHypervisorType() != null +// && ! (host.getHypervisorType() == Hypervisor.HypervisorType.KVM || host.getHypervisorType() == Hypervisor.HypervisorType.LXC)) { +// +// if (LOG.isTraceEnabled()) { +// LOG.trace(String.format("hypervisor is not the right type, not adding to the host list, (id = %s, hypervisortype = %s)", host.getUuid(), host.getHypervisorType())); +// } +// return; +// } +// +// agentBasedHosts.add(host); +// } - private void conditionallyAddHost(List agentBasedHosts, Host host) { - if (host == null) { - if (LOG.isTraceEnabled()) { - LOG.trace("trying to add no host to a list"); - } - return; + private List getAllAgentBasedHostsFromDB(final Long zoneId, final Long clusterId) { + GenericSearchBuilder sb = hostDao.createSearchBuilder(Long.class); + sb.selectFields(sb.entity().getId()); + sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); + sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); + sb.and("state", sb.entity().getResourceState(), SearchCriteria.Op.IN); + sb.and("type", sb.entity().getType(), SearchCriteria.Op.IN); + sb.done(); + SearchCriteria sc = sb.create(); + if (zoneId != null) { + sc.setParameters("zoneId", zoneId); } - - EnumSet allowedStates = EnumSet.of( + if (clusterId != null) { + sc.setParameters("clusterId", clusterId); + } + sc.setParameters("state", List.of( ResourceState.Enabled, ResourceState.Maintenance, ResourceState.Disabled, ResourceState.ErrorInMaintenance, - ResourceState.PrepareForMaintenance); - // so the remaining EnumSet disallowedStates = EnumSet.complementOf(allowedStates) - // would be {ResourceState.Creating, ResourceState.Error}; - if (!allowedStates.contains(host.getResourceState())) { - if (LOG.isTraceEnabled()) { - LOG.trace(String.format("host is in '%s' state, not adding to the host list, (id = %s)", host.getResourceState(), host.getUuid())); - } - return; - } - - if (host.getType() != Host.Type.Routing - && host.getType() != Host.Type.ConsoleProxy - && host.getType() != Host.Type.SecondaryStorage - && host.getType() != Host.Type.SecondaryStorageVM) { - if (LOG.isTraceEnabled()) { - LOG.trace(String.format("host is of wrong type, not adding to the host list, (id = %s, type = %s)", host.getUuid(), host.getType())); - } - return; - } - - if (host.getHypervisorType() != null - && ! (host.getHypervisorType() == Hypervisor.HypervisorType.KVM || host.getHypervisorType() == Hypervisor.HypervisorType.LXC)) { - - if (LOG.isTraceEnabled()) { - LOG.trace(String.format("hypervisor is not the right type, not adding to the host list, (id = %s, hypervisortype = %s)", host.getUuid(), host.getHypervisorType())); - } - return; - } - - agentBasedHosts.add(host); + ResourceState.PrepareForMaintenance).toArray()); + sc.setParameters("type", List.of(Host.Type.Routing, Host.Type.ConsoleProxy, + Host.Type.SecondaryStorage, Host.Type.SecondaryStorageVM).toArray()); + return hostDao.customSearch(sc, null); } private org.apache.cloudstack.agent.lb.IndirectAgentLBAlgorithm getAgentMSLBAlgorithm() { @@ -210,18 +235,28 @@ public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implement public void propagateMSListToAgents() { LOG.debug("Propagating management server list update to agents"); final String lbAlgorithm = getLBAlgorithmName(); - final Map> dcOrderedHostsMap = new HashMap<>(); - for (final Host host : getAllAgentBasedHosts()) { - final Long dcId = host.getDataCenterId(); - if (!dcOrderedHostsMap.containsKey(dcId)) { - dcOrderedHostsMap.put(dcId, getOrderedHostIdList(dcId)); + List zones = dataCenterDao.listAll(); + for (DataCenterVO zone : zones) { + List zoneHostIds = new ArrayList<>(); + Map> clusterHostIdsMap = new HashMap<>(); + List clusterIds = clusterDao.listAllClusterIds(zone.getId()); + for (Long clusterId : clusterIds) { + List hostIds = getAllAgentBasedHostsFromDB(zone.getId(), clusterId); + clusterHostIdsMap.put(clusterId, hostIds); + zoneHostIds.addAll(hostIds); } - final List msList = getManagementServerList(host.getId(), host.getDataCenterId(), dcOrderedHostsMap.get(dcId)); - final Long lbCheckInterval = getLBPreferredHostCheckInterval(host.getClusterId()); - final SetupMSListCommand cmd = new SetupMSListCommand(msList, lbAlgorithm, lbCheckInterval); - final Answer answer = agentManager.easySend(host.getId(), cmd); - if (answer == null || !answer.getResult()) { - LOG.warn(String.format("Failed to setup management servers list to the agent of %s", host)); + zoneHostIds.sort(Comparator.comparingLong(x -> x)); + for (Long clusterId : clusterIds) { + final Long lbCheckInterval = getLBPreferredHostCheckInterval(clusterId); + List hostIds = clusterHostIdsMap.get(clusterId); + for (Long hostId : hostIds) { + final List msList = getManagementServerList(hostId, zone.getId(), zoneHostIds); + final SetupMSListCommand cmd = new SetupMSListCommand(msList, lbAlgorithm, lbCheckInterval); + final Answer answer = agentManager.easySend(hostId, cmd); + if (answer == null || !answer.getResult()) { + LOG.warn(String.format("Failed to setup management servers list to the agent of ID: %d", hostId)); + } + } } } } From 9e5c99ef9ebea3bd54efb346d558d4b8e8ac6c32 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 12 Sep 2024 16:58:18 +0530 Subject: [PATCH 18/62] fix tests from a78a2508e955fa8c08b62e56c3440ca58bad3e77 Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/host/dao/HostDao.java | 3 ++ .../java/com/cloud/host/dao/HostDaoImpl.java | 22 +++++++++++++++ .../agent/lb/IndirectAgentLBServiceImpl.java | 28 ++++--------------- .../lb/IndirectAgentLBServiceImplTest.java | 22 ++++++++------- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java index b3752f0d68b..9842056c202 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java @@ -167,4 +167,7 @@ public interface HostDao extends GenericDao, StateDao listOrderedHostsHypervisorVersionsInDatacenter(long datacenterId, HypervisorType hypervisorType); boolean isHostUp(long hostId); + + List findHostIdsByZoneClusterResourceStateAndType(final Long zoneId, final Long clusterId, + final List resourceStates, final List types); } diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java index 4be6cb32ea6..a70c1a76fe0 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java @@ -1521,4 +1521,26 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao List statuses = customSearch(sc, null); return CollectionUtils.isNotEmpty(statuses) && Status.Up.equals(statuses.get(0)); } + + @Override + public List findHostIdsByZoneClusterResourceStateAndType(final Long zoneId, final Long clusterId, + final List resourceStates, final List types) { + GenericSearchBuilder sb = createSearchBuilder(Long.class); + sb.selectFields(sb.entity().getId()); + sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); + sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); + sb.and("resourceState", sb.entity().getResourceState(), SearchCriteria.Op.IN); + sb.and("type", sb.entity().getType(), SearchCriteria.Op.IN); + sb.done(); + SearchCriteria sc = sb.create(); + if (zoneId != null) { + sc.setParameters("zoneId", zoneId); + } + if (clusterId != null) { + sc.setParameters("clusterId", clusterId); + } + sc.setParameters("resourceState", resourceStates.toArray()); + sc.setParameters("type", types.toArray()); + return customSearch(sc, null); + } } diff --git a/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java b/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java index 0da5f193eef..b1ed6317641 100644 --- a/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java +++ b/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java @@ -193,29 +193,11 @@ public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implement // } private List getAllAgentBasedHostsFromDB(final Long zoneId, final Long clusterId) { - GenericSearchBuilder sb = hostDao.createSearchBuilder(Long.class); - sb.selectFields(sb.entity().getId()); - sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); - sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); - sb.and("state", sb.entity().getResourceState(), SearchCriteria.Op.IN); - sb.and("type", sb.entity().getType(), SearchCriteria.Op.IN); - sb.done(); - SearchCriteria sc = sb.create(); - if (zoneId != null) { - sc.setParameters("zoneId", zoneId); - } - if (clusterId != null) { - sc.setParameters("clusterId", clusterId); - } - sc.setParameters("state", List.of( - ResourceState.Enabled, - ResourceState.Maintenance, - ResourceState.Disabled, - ResourceState.ErrorInMaintenance, - ResourceState.PrepareForMaintenance).toArray()); - sc.setParameters("type", List.of(Host.Type.Routing, Host.Type.ConsoleProxy, - Host.Type.SecondaryStorage, Host.Type.SecondaryStorageVM).toArray()); - return hostDao.customSearch(sc, null); + return hostDao.findHostIdsByZoneClusterResourceStateAndType(zoneId, clusterId, + List.of(ResourceState.Enabled, ResourceState.Maintenance, ResourceState.Disabled, + ResourceState.ErrorInMaintenance, ResourceState.PrepareForMaintenance), + List.of(Host.Type.Routing, Host.Type.ConsoleProxy, + Host.Type.SecondaryStorage, Host.Type.SecondaryStorageVM)); } private org.apache.cloudstack.agent.lb.IndirectAgentLBAlgorithm getAgentMSLBAlgorithm() { diff --git a/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java b/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java index 98c2af5b776..14a29628168 100644 --- a/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java @@ -16,13 +16,16 @@ // under the License. package org.apache.cloudstack.agent.lb; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.stream.Collectors; import org.apache.cloudstack.config.ApiServiceConfiguration; import org.apache.cloudstack.framework.config.ConfigKey; @@ -32,6 +35,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.Spy; @@ -84,6 +88,7 @@ public class IndirectAgentLBServiceImplTest { } private void configureMocks() throws NoSuchFieldException, IllegalAccessException { + List hosts = Arrays.asList(host1, host2, host3, host4); long id = 1; for (HostVO h : Arrays.asList(host1, host2, host3, host4)) { when(h.getId()).thenReturn(id); @@ -97,7 +102,9 @@ public class IndirectAgentLBServiceImplTest { addField(agentMSLB, "hostDao", hostDao); addField(agentMSLB, "agentManager", agentManager); - when(hostDao.listAll()).thenReturn(Arrays.asList(host4, host2, host1, host3)); + List hostIds = hosts.stream().map(HostVO::getId).collect(Collectors.toList()); + doReturn(hostIds).when(hostDao).findHostIdsByZoneClusterResourceStateAndType(Mockito.anyLong(), Mockito.eq(null), + Mockito.anyList(), Mockito.anyList()); } @Before @@ -187,9 +194,10 @@ public class IndirectAgentLBServiceImplTest { } @Test - public void testGetOrderedRunningHostIdsNullList() { - when(hostDao.listAll()).thenReturn(null); - Assert.assertTrue(agentMSLB.getOrderedHostIdList(DC_1_ID).size() == 0); + public void testGetOrderedRunningHostIdsEmptyList() { + doReturn(Collections.emptyList()).when(hostDao).findHostIdsByZoneClusterResourceStateAndType(Mockito.eq(DC_1_ID), Mockito.eq(null), + Mockito.anyList(), Mockito.anyList()); + Assert.assertTrue(agentMSLB.getOrderedHostIdList(DC_1_ID).isEmpty()); } @Test @@ -198,10 +206,4 @@ public class IndirectAgentLBServiceImplTest { Assert.assertEquals(Arrays.asList(host1.getId(), host2.getId(), host3.getId(), host4.getId()), agentMSLB.getOrderedHostIdList(DC_1_ID)); } - - @Test - public void testGetHostsPerZoneNullHosts() { - when(hostDao.listAll()).thenReturn(null); - Assert.assertTrue(agentMSLB.getOrderedHostIdList(DC_2_ID).size() == 0); - } } From eb749746853e43a9b99eb93f7d55fb0894e066cb Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 12 Sep 2024 17:00:57 +0530 Subject: [PATCH 19/62] more test fix Signed-off-by: Abhishek Kumar --- .../cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java b/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java index 14a29628168..84997b8dc6d 100644 --- a/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImplTest.java @@ -202,7 +202,9 @@ public class IndirectAgentLBServiceImplTest { @Test public void testGetOrderedRunningHostIdsOrderList() { - when(hostDao.listAll()).thenReturn(Arrays.asList(host4, host2, host1, host3)); + doReturn(Arrays.asList(host4.getId(), host2.getId(), host1.getId(), host3.getId())).when(hostDao) + .findHostIdsByZoneClusterResourceStateAndType(Mockito.eq(DC_1_ID), Mockito.eq(null), + Mockito.anyList(), Mockito.anyList()); Assert.assertEquals(Arrays.asList(host1.getId(), host2.getId(), host3.getId(), host4.getId()), agentMSLB.getOrderedHostIdList(DC_1_ID)); } From ad275e7a36bc54a14e379c55e37bcbe44c48c3cc Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 12 Sep 2024 17:21:00 +0530 Subject: [PATCH 20/62] remove dead code Signed-off-by: Abhishek Kumar --- .../agent/lb/IndirectAgentLBServiceImpl.java | 60 ------------------- 1 file changed, 60 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java b/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java index b1ed6317641..b6e7d81ffa4 100644 --- a/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java +++ b/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java @@ -41,12 +41,9 @@ import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.host.Host; -import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.resource.ResourceState; import com.cloud.utils.component.ComponentLifecycleBase; -import com.cloud.utils.db.GenericSearchBuilder; -import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.exception.CloudRuntimeException; public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implements IndirectAgentLB, Configurable { @@ -135,63 +132,6 @@ public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implement return hostIdList; } -// private List getAllAgentBasedHosts() { -// final List allHosts = hostDao.listAll(); -// if (allHosts == null) { -// return new ArrayList<>(); -// } -// final List agentBasedHosts = new ArrayList<>(); -// for (final Host host : allHosts) { -// conditionallyAddHost(agentBasedHosts, host); -// } -// return agentBasedHosts; -// } -// -// private void conditionallyAddHost(List agentBasedHosts, Host host) { -// if (host == null) { -// if (LOG.isTraceEnabled()) { -// LOG.trace("trying to add no host to a list"); -// } -// return; -// } -// -// EnumSet allowedStates = EnumSet.of( -// ResourceState.Enabled, -// ResourceState.Maintenance, -// ResourceState.Disabled, -// ResourceState.ErrorInMaintenance, -// ResourceState.PrepareForMaintenance); -// // so the remaining EnumSet disallowedStates = EnumSet.complementOf(allowedStates) -// // would be {ResourceState.Creating, ResourceState.Error}; -// if (!allowedStates.contains(host.getResourceState())) { -// if (LOG.isTraceEnabled()) { -// LOG.trace(String.format("host is in '%s' state, not adding to the host list, (id = %s)", host.getResourceState(), host.getUuid())); -// } -// return; -// } -// -// if (host.getType() != Host.Type.Routing -// && host.getType() != Host.Type.ConsoleProxy -// && host.getType() != Host.Type.SecondaryStorage -// && host.getType() != Host.Type.SecondaryStorageVM) { -// if (LOG.isTraceEnabled()) { -// LOG.trace(String.format("host is of wrong type, not adding to the host list, (id = %s, type = %s)", host.getUuid(), host.getType())); -// } -// return; -// } -// -// if (host.getHypervisorType() != null -// && ! (host.getHypervisorType() == Hypervisor.HypervisorType.KVM || host.getHypervisorType() == Hypervisor.HypervisorType.LXC)) { -// -// if (LOG.isTraceEnabled()) { -// LOG.trace(String.format("hypervisor is not the right type, not adding to the host list, (id = %s, hypervisortype = %s)", host.getUuid(), host.getHypervisorType())); -// } -// return; -// } -// -// agentBasedHosts.add(host); -// } - private List getAllAgentBasedHostsFromDB(final Long zoneId, final Long clusterId) { return hostDao.findHostIdsByZoneClusterResourceStateAndType(zoneId, clusterId, List.of(ResourceState.Enabled, ResourceState.Maintenance, ResourceState.Disabled, From a1ee64344dfe26f64ebbe545bf623a15654f1880 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 12 Sep 2024 17:23:44 +0530 Subject: [PATCH 21/62] address host/cluster dao listall Signed-off-by: Abhishek Kumar --- .../java/com/cloud/dc/dao/ClusterDao.java | 10 +++--- .../java/com/cloud/dc/dao/ClusterDaoImpl.java | 34 ++++++++++++------- .../main/java/com/cloud/host/dao/HostDao.java | 2 ++ .../java/com/cloud/host/dao/HostDaoImpl.java | 8 +++++ .../metrics/PrometheusExporterImpl.java | 4 +-- .../datastore/util/StorPoolHelper.java | 14 ++++---- 6 files changed, 47 insertions(+), 25 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java index 1f31734f355..15fdafc50c1 100644 --- a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java +++ b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java @@ -16,14 +16,14 @@ // under the License. package com.cloud.dc.dao; -import com.cloud.dc.ClusterVO; -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.utils.db.GenericDao; - import java.util.List; import java.util.Map; import java.util.Set; +import com.cloud.dc.ClusterVO; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.utils.db.GenericDao; + public interface ClusterDao extends GenericDao { List listByPodId(long podId); @@ -54,4 +54,6 @@ public interface ClusterDao extends GenericDao { List listAllClusterIds(Long zoneId); boolean getSupportsResigning(long clusterId); + + List listAllIds(); } diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java index 4632d168c50..a59ae3e19bd 100644 --- a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java @@ -16,6 +16,20 @@ // under the License. package com.cloud.dc.dao; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +import org.springframework.stereotype.Component; + import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsVO; import com.cloud.dc.ClusterVO; @@ -32,18 +46,6 @@ import com.cloud.utils.db.SearchCriteria.Func; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.exception.CloudRuntimeException; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; @Component public class ClusterDaoImpl extends GenericDaoBase implements ClusterDao { @@ -309,4 +311,12 @@ public class ClusterDaoImpl extends GenericDaoBase implements C return false; } + + @Override + public List listAllIds() { + GenericSearchBuilder sb = createSearchBuilder(Long.class); + sb.selectFields(sb.entity().getId()); + sb.done(); + return customSearch(sb.create(), null); + } } diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java index 9842056c202..12a54d15ea1 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java @@ -170,4 +170,6 @@ public interface HostDao extends GenericDao, StateDao findHostIdsByZoneClusterResourceStateAndType(final Long zoneId, final Long clusterId, final List resourceStates, final List types); + + List listAllIds(); } diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java index a70c1a76fe0..363b5bbf3cd 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java @@ -1543,4 +1543,12 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao sc.setParameters("type", types.toArray()); return customSearch(sc, null); } + + @Override + public List listAllIds() { + GenericSearchBuilder sb = createSearchBuilder(Long.class); + sb.selectFields(sb.entity().getId()); + sb.done(); + return customSearch(sb.create(), null); + } } diff --git a/plugins/integrations/prometheus/src/main/java/org/apache/cloudstack/metrics/PrometheusExporterImpl.java b/plugins/integrations/prometheus/src/main/java/org/apache/cloudstack/metrics/PrometheusExporterImpl.java index b82b216ef59..a539e110bfe 100644 --- a/plugins/integrations/prometheus/src/main/java/org/apache/cloudstack/metrics/PrometheusExporterImpl.java +++ b/plugins/integrations/prometheus/src/main/java/org/apache/cloudstack/metrics/PrometheusExporterImpl.java @@ -263,8 +263,8 @@ public class PrometheusExporterImpl extends ManagerBase implements PrometheusExp metricsList.add(new ItemHostMemory(zoneName, zoneUuid, null, null, null, null, ALLOCATED, allocatedCapacityByTag.third(), 0, tag)); }); - List allHostTags = hostDao.listAll().stream() - .flatMap( h -> _hostTagsDao.getHostTags(h.getId()).stream()) + List allHostTags = hostDao.listAllIds().stream() + .flatMap( h -> _hostTagsDao.getHostTags(h).stream()) .distinct() .collect(Collectors.toList()); diff --git a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/util/StorPoolHelper.java b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/util/StorPoolHelper.java index 9395f134fe1..f71962de023 100644 --- a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/util/StorPoolHelper.java +++ b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/util/StorPoolHelper.java @@ -225,17 +225,17 @@ public class StorPoolHelper { } public static Long findClusterIdByGlobalId(String globalId, ClusterDao clusterDao) { - List clusterVo = clusterDao.listAll(); - if (clusterVo.size() == 1) { + List clusterIds = clusterDao.listAllIds(); + if (clusterIds.size() == 1) { StorPoolUtil.spLog("There is only one cluster, sending backup to secondary command"); return null; } - for (ClusterVO clusterVO2 : clusterVo) { - if (globalId != null && StorPoolConfigurationManager.StorPoolClusterId.valueIn(clusterVO2.getId()) != null - && globalId.contains(StorPoolConfigurationManager.StorPoolClusterId.valueIn(clusterVO2.getId()).toString())) { - StorPoolUtil.spLog("Found cluster with id=%s for object with globalId=%s", clusterVO2.getId(), + for (Long clusterId : clusterIds) { + if (globalId != null && StorPoolConfigurationManager.StorPoolClusterId.valueIn(clusterId) != null + && globalId.contains(StorPoolConfigurationManager.StorPoolClusterId.valueIn(clusterId))) { + StorPoolUtil.spLog("Found cluster with id=%s for object with globalId=%s", clusterId, globalId); - return clusterVO2.getId(); + return clusterId; } } throw new CloudRuntimeException( From e1a5bd9ef2d650dbdcd038e51434f82a402bf69c Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 13 Sep 2024 10:25:31 +0530 Subject: [PATCH 22/62] improve agentlb sort when host list not needed Signed-off-by: Abhishek Kumar --- .../apache/cloudstack/agent/lb/IndirectAgentLBAlgorithm.java | 4 ++++ .../cloudstack/agent/lb/IndirectAgentLBServiceImpl.java | 5 ++--- .../lb/algorithm/IndirectAgentLBRoundRobinAlgorithm.java | 5 +++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/framework/agent-lb/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBAlgorithm.java b/framework/agent-lb/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBAlgorithm.java index c87a0996fcc..062d2226876 100644 --- a/framework/agent-lb/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBAlgorithm.java +++ b/framework/agent-lb/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBAlgorithm.java @@ -42,4 +42,8 @@ public interface IndirectAgentLBAlgorithm { * @return true if the lists are equal, false if not */ boolean compare(final List msList, final List receivedMsList); + + default boolean isHostListNeeded() { + return false; + } } diff --git a/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java b/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java index b6e7d81ffa4..109348aa063 100644 --- a/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java +++ b/server/src/main/java/org/apache/cloudstack/agent/lb/IndirectAgentLBServiceImpl.java @@ -86,9 +86,10 @@ public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implement return msList; } + final org.apache.cloudstack.agent.lb.IndirectAgentLBAlgorithm algorithm = getAgentMSLBAlgorithm(); List hostIdList = orderedHostIdList; if (hostIdList == null) { - hostIdList = getOrderedHostIdList(dcId); + hostIdList = algorithm.isHostListNeeded() ? getOrderedHostIdList(dcId) : new ArrayList<>(); } // just in case we have a host in creating state make sure it is in the list: @@ -98,8 +99,6 @@ public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implement } hostIdList.add(hostId); } - - final org.apache.cloudstack.agent.lb.IndirectAgentLBAlgorithm algorithm = getAgentMSLBAlgorithm(); return algorithm.sort(msList, hostIdList, hostId); } diff --git a/server/src/main/java/org/apache/cloudstack/agent/lb/algorithm/IndirectAgentLBRoundRobinAlgorithm.java b/server/src/main/java/org/apache/cloudstack/agent/lb/algorithm/IndirectAgentLBRoundRobinAlgorithm.java index 63fea5e74e6..49e6899aaeb 100644 --- a/server/src/main/java/org/apache/cloudstack/agent/lb/algorithm/IndirectAgentLBRoundRobinAlgorithm.java +++ b/server/src/main/java/org/apache/cloudstack/agent/lb/algorithm/IndirectAgentLBRoundRobinAlgorithm.java @@ -56,4 +56,9 @@ public class IndirectAgentLBRoundRobinAlgorithm implements IndirectAgentLBAlgori public boolean compare(final List msList, final List receivedMsList) { return msList != null && receivedMsList != null && msList.equals(receivedMsList); } + + @Override + public boolean isHostListNeeded() { + return true; + } } From 38d6c4e7e7d7535e08f1e45dad0f4e5fd1eb2239 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 13 Sep 2024 12:10:47 +0530 Subject: [PATCH 23/62] optimize finding ready systemvm template for zone Retrieving templates with inner join on host table was turning out to be more expensive than finding distinct hypervisor types for a zone using hsot table and then finding templates for those types Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/host/dao/HostDao.java | 2 + .../java/com/cloud/host/dao/HostDaoImpl.java | 13 ++++++ .../cloud/storage/dao/VMTemplateDaoImpl.java | 46 +++++++++---------- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java index 12a54d15ea1..6fe272f1515 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java @@ -172,4 +172,6 @@ public interface HostDao extends GenericDao, StateDao resourceStates, final List types); List listAllIds(); + + List findDistinctHypervisorTypesForZone(final long zoneId); } diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java index 363b5bbf3cd..2ffdc3585a4 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java @@ -1551,4 +1551,17 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao sb.done(); return customSearch(sb.create(), null); } + + @Override + public List findDistinctHypervisorTypesForZone(long zoneId) { + GenericSearchBuilder sb = createSearchBuilder(HypervisorType.class); + sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); + sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ); + sb.select(null, Func.DISTINCT, sb.entity().getHypervisorType()); + sb.done(); + SearchCriteria sc = sb.create(); + sc.setParameters("zoneId", zoneId); + sc.setParameters("type", Type.Routing); + return customSearch(sc, null); + } } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java index 84643beb83d..6e0dc5cbeea 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -17,6 +17,7 @@ package com.cloud.storage.dao; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; @@ -26,6 +27,7 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -343,19 +345,11 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem readySystemTemplateSearch = createSearchBuilder(); readySystemTemplateSearch.and("state", readySystemTemplateSearch.entity().getState(), SearchCriteria.Op.EQ); readySystemTemplateSearch.and("templateType", readySystemTemplateSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); + readySystemTemplateSearch.and("hypervisorType", readySystemTemplateSearch.entity().getHypervisorType(), SearchCriteria.Op.IN); SearchBuilder templateDownloadSearch = _templateDataStoreDao.createSearchBuilder(); templateDownloadSearch.and("downloadState", templateDownloadSearch.entity().getDownloadState(), SearchCriteria.Op.IN); readySystemTemplateSearch.join("vmTemplateJoinTemplateStoreRef", templateDownloadSearch, templateDownloadSearch.entity().getTemplateId(), readySystemTemplateSearch.entity().getId(), JoinBuilder.JoinType.INNER); - SearchBuilder hostHyperSearch2 = _hostDao.createSearchBuilder(); - hostHyperSearch2.and("type", hostHyperSearch2.entity().getType(), SearchCriteria.Op.EQ); - hostHyperSearch2.and("zoneId", hostHyperSearch2.entity().getDataCenterId(), SearchCriteria.Op.EQ); - hostHyperSearch2.and("removed", hostHyperSearch2.entity().getRemoved(), SearchCriteria.Op.NULL); - hostHyperSearch2.groupBy(hostHyperSearch2.entity().getHypervisorType()); - - readySystemTemplateSearch.join("tmplHyper", hostHyperSearch2, hostHyperSearch2.entity().getHypervisorType(), readySystemTemplateSearch.entity() - .getHypervisorType(), JoinBuilder.JoinType.INNER); - hostHyperSearch2.done(); readySystemTemplateSearch.groupBy(readySystemTemplateSearch.entity().getId()); readySystemTemplateSearch.done(); @@ -552,32 +546,34 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem @Override public List listAllReadySystemVMTemplates(Long zoneId) { + List availableHypervisors = _hostDao.findDistinctHypervisorTypesForZone(zoneId); + if (CollectionUtils.isEmpty(availableHypervisors)) { + return Collections.emptyList(); + } SearchCriteria sc = readySystemTemplateSearch.create(); sc.setParameters("templateType", Storage.TemplateType.SYSTEM); sc.setParameters("state", VirtualMachineTemplate.State.Active); - sc.setJoinParameters("tmplHyper", "type", Host.Type.Routing); - if (zoneId != null) { - sc.setJoinParameters("tmplHyper", "zoneId", zoneId); - } - sc.setJoinParameters("vmTemplateJoinTemplateStoreRef", "downloadState", new VMTemplateStorageResourceAssoc.Status[] {VMTemplateStorageResourceAssoc.Status.DOWNLOADED, VMTemplateStorageResourceAssoc.Status.BYPASSED}); + sc.setParameters("hypervisorType", availableHypervisors.toArray()); + sc.setJoinParameters("vmTemplateJoinTemplateStoreRef", "downloadState", + List.of(VMTemplateStorageResourceAssoc.Status.DOWNLOADED, + VMTemplateStorageResourceAssoc.Status.BYPASSED).toArray()); // order by descending order of id return listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, null)); } @Override public VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType) { - List tmplts = listAllReadySystemVMTemplates(zoneId); - if (tmplts.size() > 0) { - if (hypervisorType == HypervisorType.Any) { - return tmplts.get(0); - } - for (VMTemplateVO tmplt : tmplts) { - if (tmplt.getHypervisorType() == hypervisorType) { - return tmplt; - } - } + List templates = listAllReadySystemVMTemplates(zoneId); + if (CollectionUtils.isEmpty(templates)) { + return null; } - return null; + if (hypervisorType == HypervisorType.Any) { + return templates.get(0); + } + return templates.stream() + .filter(t -> t.getHypervisorType() == hypervisorType) + .findFirst() + .orElse(null); } @Override From 98b27a409dd6842d2c59f99fa746b8dbcea80081 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 13 Sep 2024 15:06:33 +0530 Subject: [PATCH 24/62] engine-schema: fix get host type count searchcriteria Signed-off-by: Abhishek Kumar --- .../src/main/java/com/cloud/host/dao/HostDaoImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java index 2ffdc3585a4..194cacfce99 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java @@ -183,6 +183,8 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao HostTypeCountSearch = createSearchBuilder(); HostTypeCountSearch.and("type", HostTypeCountSearch.entity().getType(), SearchCriteria.Op.EQ); + HostTypeCountSearch.and("zoneId", HostTypeCountSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + HostTypeCountSearch.and("resourceState", HostTypeCountSearch.entity().getResourceState(), SearchCriteria.Op.EQ); HostTypeCountSearch.done(); ResponsibleMsCountSearch = createSearchBuilder(); @@ -500,7 +502,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao public Integer countAllByTypeInZone(long zoneId, Type type) { SearchCriteria sc = HostTypeCountSearch.create(); sc.setParameters("type", type); - sc.setParameters("dc", zoneId); + sc.setParameters("zoneId", zoneId); return getCount(sc); } @@ -509,7 +511,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao SearchCriteria sc = HostTypeCountSearch.create(); sc.setParameters("type", Type.Routing); sc.setParameters("resourceState", ResourceState.Enabled); - sc.setParameters("dc", zoneId); + sc.setParameters("zoneId", zoneId); return getCount(sc); } From fe4ef05053c513f8b8601ac2627e2333953ff892 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 13 Sep 2024 16:17:47 +0530 Subject: [PATCH 25/62] server,engine-schema: use single query to to list host capacities while host capacity update Signed-off-by: Abhishek Kumar --- .../com/cloud/capacity/dao/CapacityDao.java | 2 ++ .../cloud/capacity/dao/CapacityDaoImpl.java | 12 ++++++++++ .../cloud/capacity/CapacityManagerImpl.java | 22 ++++++++++++++++--- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/capacity/dao/CapacityDao.java b/engine/schema/src/main/java/com/cloud/capacity/dao/CapacityDao.java index 9616f31d0c5..1bb79ce417a 100644 --- a/engine/schema/src/main/java/com/cloud/capacity/dao/CapacityDao.java +++ b/engine/schema/src/main/java/com/cloud/capacity/dao/CapacityDao.java @@ -28,6 +28,8 @@ import com.cloud.utils.db.GenericDao; public interface CapacityDao extends GenericDao { CapacityVO findByHostIdType(Long hostId, short capacityType); + List listByHostIdTypes(Long hostId, List capacityTypes); + List listClustersInZoneOrPodByHostCapacities(long id, long vmId, int requiredCpu, long requiredRam, short capacityTypeForOrdering, boolean isZone); List listHostsWithEnoughCapacity(int requiredCpu, long requiredRam, Long clusterId, String hostType); diff --git a/engine/schema/src/main/java/com/cloud/capacity/dao/CapacityDaoImpl.java b/engine/schema/src/main/java/com/cloud/capacity/dao/CapacityDaoImpl.java index ae75ca49f33..5f6cf9c5083 100644 --- a/engine/schema/src/main/java/com/cloud/capacity/dao/CapacityDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/capacity/dao/CapacityDaoImpl.java @@ -674,6 +674,18 @@ public class CapacityDaoImpl extends GenericDaoBase implements return findOneBy(sc); } + @Override + public List listByHostIdTypes(Long hostId, List capacityTypes) { + SearchBuilder sb = createSearchBuilder(); + sb.and("hostId", sb.entity().getHostOrPoolId(), SearchCriteria.Op.EQ); + sb.and("type", sb.entity().getCapacityType(), SearchCriteria.Op.IN); + sb.done(); + SearchCriteria sc = sb.create(); + sc.setParameters("hostId", hostId); + sc.setParameters("type", capacityTypes.toArray()); + return listBy(sc); + } + @Override public List listClustersInZoneOrPodByHostCapacities(long id, long vmId, int requiredCpu, long requiredRam, short capacityTypeForOrdering, boolean isZone) { TransactionLegacy txn = TransactionLegacy.currentTxn(); diff --git a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java index abb67e7e714..486e90b8520 100644 --- a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java @@ -41,6 +41,7 @@ import org.apache.cloudstack.utils.cache.LazyCache; import org.apache.cloudstack.utils.cache.SingleCache; import org.apache.cloudstack.utils.executor.QueuedExecutor; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -801,9 +802,24 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, } } - CapacityVO cpuCap = _capacityDao.findByHostIdType(host.getId(), Capacity.CAPACITY_TYPE_CPU); - CapacityVO memCap = _capacityDao.findByHostIdType(host.getId(), Capacity.CAPACITY_TYPE_MEMORY); - CapacityVO cpuCoreCap = _capacityDao.findByHostIdType(host.getId(), CapacityVO.CAPACITY_TYPE_CPU_CORE); + List capacities = _capacityDao.listByHostIdTypes(host.getId(), List.of(Capacity.CAPACITY_TYPE_CPU, + Capacity.CAPACITY_TYPE_MEMORY, + CapacityVO.CAPACITY_TYPE_CPU_CORE)); + CapacityVO cpuCap = null; + CapacityVO memCap = null; + CapacityVO cpuCoreCap = null; + for (CapacityVO c : capacities) { + if (c.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) { + cpuCap = c; + } else if (c.getCapacityType() == Capacity.CAPACITY_TYPE_MEMORY) { + memCap = c; + } else if (c.getCapacityType() == Capacity.CAPACITY_TYPE_CPU_CORE) { + cpuCoreCap = c; + } + if (ObjectUtils.allNotNull(cpuCap, memCap, cpuCoreCap)) { + break; + } + } if (cpuCoreCap != null) { long hostTotalCpuCore = host.getCpus().longValue(); From 1d47e4d4ae177e4a9f41c12b6d72c0ca011a3f1a Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 13 Sep 2024 16:19:43 +0530 Subject: [PATCH 26/62] engine-schema,server,plugins: list host IDs instead whole row where applicable Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/host/dao/HostDao.java | 4 ++ .../java/com/cloud/host/dao/HostDaoImpl.java | 22 ++++++-- .../deploy/ImplicitDedicationPlanner.java | 50 ++++++++----------- .../implicitplanner/ImplicitPlannerTest.java | 38 +++++--------- .../discoverer/XcpServerDiscoverer.java | 9 ++-- .../discoverer/LibvirtServerDiscoverer.java | 9 ++-- .../cloud/resource/ResourceManagerImpl.java | 21 ++++---- .../cloud/server/ManagementServerImpl.java | 14 +++--- 8 files changed, 81 insertions(+), 86 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java index 6fe272f1515..5a0af88fb8f 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java @@ -81,6 +81,8 @@ public interface HostDao extends GenericDao, StateDao findHypervisorHostInCluster(long clusterId); + HostVO findAnyStateHypervisorHostInCluster(long clusterId); + HostVO findOldestExistentHypervisorHostInCluster(long clusterId); List listAllUpAndEnabledNonHAHosts(Type type, Long clusterId, Long podId, long dcId, String haTag); @@ -174,4 +176,6 @@ public interface HostDao extends GenericDao, StateDao listAllIds(); List findDistinctHypervisorTypesForZone(final long zoneId); + + List listAllHostIdsInCluster(final long clusterId); } diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java index 194cacfce99..c7a0b72e936 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java @@ -456,6 +456,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao HostIdSearch = createSearchBuilder(Long.class); HostIdSearch.selectFields(HostIdSearch.entity().getId()); HostIdSearch.and("dataCenterId", HostIdSearch.entity().getDataCenterId(), Op.EQ); + HostIdSearch.and("clusterId", HostIdSearch.entity().getClusterId(), Op.EQ); HostIdSearch.done(); _statusAttr = _allAttributes.get("status"); @@ -1255,6 +1256,15 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao return listBy(sc); } + @Override + public HostVO findAnyStateHypervisorHostInCluster(long clusterId) { + SearchCriteria sc = TypeClusterStatusSearch.create(); + sc.setParameters("type", Host.Type.Routing); + sc.setParameters("cluster", clusterId); + List list = listBy(sc, new Filter(1)); + return list.isEmpty() ? null : list.get(0); + } + @Override public HostVO findOldestExistentHypervisorHostInCluster(long clusterId) { SearchCriteria sc = TypeClusterStatusSearch.create(); @@ -1548,10 +1558,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao @Override public List listAllIds() { - GenericSearchBuilder sb = createSearchBuilder(Long.class); - sb.selectFields(sb.entity().getId()); - sb.done(); - return customSearch(sb.create(), null); + return customSearch(HostIdSearch.create(), null); } @Override @@ -1566,4 +1573,11 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao sc.setParameters("type", Type.Routing); return customSearch(sc, null); } + + @Override + public List listAllHostIdsInCluster(final long clusterId) { + SearchCriteria sc = HostIdSearch.create(); + sc.setParameters("clusterId", clusterId); + return customSearch(sc, null); + } } diff --git a/plugins/deployment-planners/implicit-dedication/src/main/java/com/cloud/deploy/ImplicitDedicationPlanner.java b/plugins/deployment-planners/implicit-dedication/src/main/java/com/cloud/deploy/ImplicitDedicationPlanner.java index 2c5a72498bc..d6cd328b454 100644 --- a/plugins/deployment-planners/implicit-dedication/src/main/java/com/cloud/deploy/ImplicitDedicationPlanner.java +++ b/plugins/deployment-planners/implicit-dedication/src/main/java/com/cloud/deploy/ImplicitDedicationPlanner.java @@ -21,15 +21,16 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Logger; import com.cloud.configuration.Config; import com.cloud.exception.InsufficientServerCapacityException; -import com.cloud.host.HostVO; import com.cloud.resource.ResourceManager; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; @@ -39,7 +40,6 @@ import com.cloud.utils.DateUtil; import com.cloud.utils.NumbersUtil; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachineProfile; -import org.springframework.util.CollectionUtils; public class ImplicitDedicationPlanner extends FirstFitPlanner implements DeploymentClusterPlanner { @@ -75,12 +75,11 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy boolean preferred = isServiceOfferingUsingPlannerInPreferredMode(vmProfile.getServiceOfferingId()); // Get the list of all the hosts in the given clusters - List allHosts = new ArrayList(); - for (Long cluster : clusterList) { - List hostsInCluster = resourceMgr.listAllHostsInCluster(cluster); - for (HostVO hostVO : hostsInCluster) { - allHosts.add(hostVO.getId()); - } + List allHosts = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(clusterList)) { + allHosts = clusterList.stream() + .flatMap(cluster -> hostDao.listAllHostIdsInCluster(cluster).stream()) + .collect(Collectors.toList()); } // Go over all the hosts in the cluster and get a list of @@ -223,20 +222,15 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy } private List getUpdatedClusterList(List clusterList, Set hostsSet) { - List updatedClusterList = new ArrayList(); - for (Long cluster : clusterList) { - List hosts = resourceMgr.listAllHostsInCluster(cluster); - Set hostsInClusterSet = new HashSet(); - for (HostVO host : hosts) { - hostsInClusterSet.add(host.getId()); - } - - if (!hostsSet.containsAll(hostsInClusterSet)) { - updatedClusterList.add(cluster); - } + if (CollectionUtils.isEmpty(clusterList)) { + return new ArrayList<>(); } - - return updatedClusterList; + return clusterList.stream() + .filter(cluster -> { + Set hostsInClusterSet = new HashSet<>(hostDao.listAllHostIdsInCluster(cluster)); + return !hostsSet.containsAll(hostsInClusterSet); + }) + .collect(Collectors.toList()); } @Override @@ -256,15 +250,11 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy Account account = vmProfile.getOwner(); // Get the list of all the hosts in the given clusters - List allHosts = new ArrayList(); - if (!CollectionUtils.isEmpty(clusterList)) { - for (Long cluster : clusterList) { - List hostsInCluster = resourceMgr.listAllHostsInCluster(cluster); - for (HostVO hostVO : hostsInCluster) { - - allHosts.add(hostVO.getId()); - } - } + List allHosts = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(clusterList)) { + allHosts = clusterList.stream() + .flatMap(cluster -> hostDao.listAllHostIdsInCluster(cluster).stream()) + .collect(Collectors.toList()); } // Go over all the hosts in the cluster and get a list of // 1. All empty hosts, not running any vms. diff --git a/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java b/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java index f1645611272..a18f2f39a8d 100644 --- a/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java +++ b/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java @@ -16,11 +16,11 @@ // under the License. package org.apache.cloudstack.implicitplanner; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.everyItem; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.everyItem; -import static org.hamcrest.Matchers.equalTo; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -36,7 +36,11 @@ import java.util.UUID; import javax.inject.Inject; -import com.cloud.user.User; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.test.utils.SpringUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -54,12 +58,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.test.utils.SpringUtils; - import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityManager; import com.cloud.capacity.dao.CapacityDao; @@ -73,7 +71,6 @@ import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.deploy.ImplicitDedicationPlanner; import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.gpu.dao.HostGpuGroupsDao; -import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDetailsDao; import com.cloud.host.dao.HostTagsDao; @@ -90,6 +87,7 @@ import com.cloud.storage.dao.VolumeDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; +import com.cloud.user.User; import com.cloud.user.UserVO; import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentContext; @@ -387,21 +385,9 @@ public class ImplicitPlannerTest { when(serviceOfferingDetailsDao.listDetailsKeyPairs(offeringId)).thenReturn(details); // Initialize hosts in clusters - HostVO host1 = mock(HostVO.class); - when(host1.getId()).thenReturn(5L); - HostVO host2 = mock(HostVO.class); - when(host2.getId()).thenReturn(6L); - HostVO host3 = mock(HostVO.class); - when(host3.getId()).thenReturn(7L); - List hostsInCluster1 = new ArrayList(); - List hostsInCluster2 = new ArrayList(); - List hostsInCluster3 = new ArrayList(); - hostsInCluster1.add(host1); - hostsInCluster2.add(host2); - hostsInCluster3.add(host3); - when(resourceMgr.listAllHostsInCluster(1)).thenReturn(hostsInCluster1); - when(resourceMgr.listAllHostsInCluster(2)).thenReturn(hostsInCluster2); - when(resourceMgr.listAllHostsInCluster(3)).thenReturn(hostsInCluster3); + when(hostDao.listAllHostIdsInCluster(1)).thenReturn(List.of(5L)); + when(hostDao.listAllHostIdsInCluster(2)).thenReturn(List.of(6L)); + when(hostDao.listAllHostIdsInCluster(3)).thenReturn(List.of(7L)); // Mock vms on each host. long offeringIdForVmsOfThisAccount = 15L; diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java index 095ba810841..da2c305b74e 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java @@ -31,6 +31,7 @@ import javax.naming.ConfigurationException; import javax.persistence.EntityExistsException; import org.apache.cloudstack.hypervisor.xenserver.XenserverConfigs; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.apache.maven.artifact.versioning.ComparableVersion; @@ -146,8 +147,8 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L sc.and(sc.entity().getGuid(), Op.EQ, guid); List clusters = sc.list(); ClusterVO clu = clusters.get(0); - List clusterHosts = _resourceMgr.listAllHostsInCluster(clu.getId()); - if (clusterHosts == null || clusterHosts.size() == 0) { + List clusterHostIds = _hostDao.listAllHostIdsInCluster(clu.getId()); + if (CollectionUtils.isEmpty(clusterHostIds)) { clu.setGuid(null); _clusterDao.update(clu.getId(), clu); _clusterDao.update(cluster.getId(), cluster); @@ -247,8 +248,8 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L if (clu.getGuid() == null) { setClusterGuid(clu, poolUuid); } else { - List clusterHosts = _resourceMgr.listAllHostsInCluster(clusterId); - if (clusterHosts != null && clusterHosts.size() > 0) { + List clusterHostIds = _hostDao.listAllHostIdsInCluster(clusterId); + if (CollectionUtils.isNotEmpty(clusterHostIds)) { if (!clu.getGuid().equals(poolUuid)) { String msg = "Please join the host " + hostIp + " to XS pool " + clu.getGuid() + " through XC/XS before adding it through CS UI"; diff --git a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java index e9f0d5f58e4..340cf632c62 100644 --- a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java +++ b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java @@ -464,11 +464,10 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements throw new IllegalArgumentException("cannot add host, due to can't find cluster: " + host.getClusterId()); } - List hostsInCluster = _resourceMgr.listAllHostsInCluster(clusterVO.getId()); - if (!hostsInCluster.isEmpty()) { - HostVO oneHost = hostsInCluster.get(0); - _hostDao.loadDetails(oneHost); - String hostOsInCluster = oneHost.getDetail("Host.OS"); + HostVO existingHostInCluster = hostDao.findAnyStateHypervisorHostInCluster(clusterVO.getId()); + if (existingHostInCluster != null) { + _hostDao.loadDetails(existingHostInCluster); + String hostOsInCluster = existingHostInCluster.getDetail("Host.OS"); String hostOs = ssCmd.getHostDetails().get("Host.OS"); if (!hostOsInCluster.equalsIgnoreCase(hostOs)) { String msg = String.format("host: %s with hostOS, \"%s\"into a cluster, in which there are \"%s\" hosts added", firstCmd.getPrivateIpAddress(), hostOs, hostOsInCluster); diff --git a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java index 0160d347c27..6aa733a9a50 100755 --- a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java @@ -643,8 +643,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, throw ex; } else { if (cluster.getGuid() == null) { - final List hosts = listAllHostsInCluster(clusterId); - if (!hosts.isEmpty()) { + final List hostIds = _hostDao.listAllHostIdsInCluster(clusterId); + if (!hostIds.isEmpty()) { final CloudRuntimeException ex = new CloudRuntimeException("Guid is not updated for cluster with specified cluster id; need to wait for hosts in this cluster to come up"); ex.addProxyObject(cluster.getUuid(), "clusterId"); @@ -962,8 +962,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, Host hostRemoved = _hostDao.findById(hostId); _hostDao.remove(hostId); if (clusterId != null) { - final List hosts = listAllHostsInCluster(clusterId); - if (hosts.size() == 0) { + final List hostIds = _hostDao.listAllHostIdsInCluster(clusterId); + if (CollectionUtils.isEmpty(hostIds)) { final ClusterVO cluster = _clusterDao.findById(clusterId); cluster.setGuid(null); _clusterDao.update(clusterId, cluster); @@ -1087,8 +1087,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, final Hypervisor.HypervisorType hypervisorType = cluster.getHypervisorType(); - final List hosts = listAllHostsInCluster(cmd.getId()); - if (hosts.size() > 0) { + final List hostIds = _hostDao.listAllHostIdsInCluster(cmd.getId()); + if (!hostIds.isEmpty()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Cluster: " + cmd.getId() + " still has hosts, can't remove"); } @@ -3034,10 +3034,10 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, public boolean updateClusterPassword(final UpdateHostPasswordCmd command) { final boolean shouldUpdateHostPasswd = command.getUpdatePasswdOnHost(); // get agents for the cluster - final List hosts = listAllHostsInCluster(command.getClusterId()); - for (final HostVO host : hosts) { + final List hostIds = _hostDao.listAllHostIdsInCluster(command.getClusterId()); + for (final Long hostId : hostIds) { try { - final Boolean result = propagateResourceEvent(host.getId(), ResourceState.Event.UpdatePassword); + final Boolean result = propagateResourceEvent(hostId, ResourceState.Event.UpdatePassword); if (result != null) { return result; } @@ -3046,8 +3046,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } if (shouldUpdateHostPasswd) { - final boolean isUpdated = doUpdateHostPassword(host.getId()); + final boolean isUpdated = doUpdateHostPassword(hostId); if (!isUpdated) { + HostVO host = _hostDao.findById(hostId); throw new CloudRuntimeException( String.format("CloudStack failed to update the password of %s. Please make sure you are still able to connect to your hosts.", host)); } diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index dc44fbd0bdb..81422e3dbf9 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -4860,7 +4860,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private boolean updateHostsInCluster(final UpdateHostPasswordCmd command) { // get all the hosts in this cluster - final List hosts = _resourceMgr.listAllHostsInCluster(command.getClusterId()); + final List hostIds = _hostDao.listAllHostIdsInCluster(command.getClusterId()); String userNameWithoutSpaces = StringUtils.deleteWhitespace(command.getUsername()); if (StringUtils.isBlank(userNameWithoutSpaces)) { @@ -4870,19 +4870,19 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(final TransactionStatus status) { - for (final HostVO h : hosts) { + for (final Long hostId : hostIds) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Changing password for host name = " + h.getName()); + s_logger.debug("Changing password for host ID: " + hostId); } // update password for this host - final DetailVO nv = _detailsDao.findDetail(h.getId(), ApiConstants.USERNAME); + final DetailVO nv = _detailsDao.findDetail(hostId, ApiConstants.USERNAME); if (nv == null) { - final DetailVO nvu = new DetailVO(h.getId(), ApiConstants.USERNAME, userNameWithoutSpaces); + final DetailVO nvu = new DetailVO(hostId, ApiConstants.USERNAME, userNameWithoutSpaces); _detailsDao.persist(nvu); - final DetailVO nvp = new DetailVO(h.getId(), ApiConstants.PASSWORD, DBEncryptionUtil.encrypt(command.getPassword())); + final DetailVO nvp = new DetailVO(hostId, ApiConstants.PASSWORD, DBEncryptionUtil.encrypt(command.getPassword())); _detailsDao.persist(nvp); } else if (nv.getValue().equals(userNameWithoutSpaces)) { - final DetailVO nvp = _detailsDao.findDetail(h.getId(), ApiConstants.PASSWORD); + final DetailVO nvp = _detailsDao.findDetail(hostId, ApiConstants.PASSWORD); nvp.setValue(DBEncryptionUtil.encrypt(command.getPassword())); _detailsDao.persist(nvp); } else { From 97ddd17f94826effbca8e47a01a94b03be1b9488 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 13 Sep 2024 17:40:20 +0530 Subject: [PATCH 27/62] fix related to 38d6c4e7e7d7535e08f1e45dad0f4e5fd1eb2239 Signed-off-by: Abhishek Kumar --- .../com/cloud/storage/dao/VMTemplateDaoImpl.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java index 6e0dc5cbeea..7e82b96462d 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -546,14 +546,19 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem @Override public List listAllReadySystemVMTemplates(Long zoneId) { - List availableHypervisors = _hostDao.findDistinctHypervisorTypesForZone(zoneId); - if (CollectionUtils.isEmpty(availableHypervisors)) { - return Collections.emptyList(); + List availableHypervisors = null; + if (zoneId != null) { + availableHypervisors = _hostDao.findDistinctHypervisorTypesForZone(zoneId); + if (CollectionUtils.isEmpty(availableHypervisors)) { + return Collections.emptyList(); + } } SearchCriteria sc = readySystemTemplateSearch.create(); sc.setParameters("templateType", Storage.TemplateType.SYSTEM); sc.setParameters("state", VirtualMachineTemplate.State.Active); - sc.setParameters("hypervisorType", availableHypervisors.toArray()); + if (CollectionUtils.isNotEmpty(availableHypervisors)) { + sc.setParameters("hypervisorType", availableHypervisors.toArray()); + } sc.setJoinParameters("vmTemplateJoinTemplateStoreRef", "downloadState", List.of(VMTemplateStorageResourceAssoc.Status.DOWNLOADED, VMTemplateStorageResourceAssoc.Status.BYPASSED).toArray()); From 99115b9f09b4551c01f2a302108c073da4957a8f Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 13 Sep 2024 18:05:54 +0530 Subject: [PATCH 28/62] server: cache cluster host type retrievals during connections Signed-off-by: Abhishek Kumar --- .../discoverer/LibvirtServerDiscoverer.java | 59 ++++++++++++------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java index 340cf632c62..3b30c2749a6 100644 --- a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java +++ b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java @@ -16,6 +16,29 @@ // under the License. package com.cloud.hypervisor.kvm.discoverer; +import static com.cloud.configuration.ConfigurationManagerImpl.ADD_HOST_ON_SERVICE_RESTART_KVM; + +import java.net.InetAddress; +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.agent.lb.IndirectAgentLB; +import org.apache.cloudstack.ca.CAManager; +import org.apache.cloudstack.ca.SetupCertificateCommand; +import org.apache.cloudstack.direct.download.DirectDownloadManager; +import org.apache.cloudstack.framework.ca.Certificate; +import org.apache.cloudstack.utils.cache.LazyCache; +import org.apache.cloudstack.utils.security.KeyStoreUtils; +import org.apache.log4j.Logger; + import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; import com.cloud.agent.api.AgentControlAnswer; @@ -48,26 +71,6 @@ import com.cloud.utils.StringUtils; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.ssh.SSHCmdHelper; import com.trilead.ssh2.Connection; -import org.apache.cloudstack.agent.lb.IndirectAgentLB; -import org.apache.cloudstack.ca.CAManager; -import org.apache.cloudstack.ca.SetupCertificateCommand; -import org.apache.cloudstack.direct.download.DirectDownloadManager; -import org.apache.cloudstack.framework.ca.Certificate; -import org.apache.cloudstack.utils.security.KeyStoreUtils; -import org.apache.log4j.Logger; - -import javax.inject.Inject; -import javax.naming.ConfigurationException; -import java.net.InetAddress; -import java.net.URI; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import static com.cloud.configuration.ConfigurationManagerImpl.ADD_HOST_ON_SERVICE_RESTART_KVM; public abstract class LibvirtServerDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(LibvirtServerDiscoverer.class); @@ -86,6 +89,16 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements @Inject private HostDao hostDao; + private LazyCache clusterExistingHostCache; + + private HostVO getExistingHostForCluster(long clusterId) { + HostVO existingHostInCluster = _hostDao.findAnyStateHypervisorHostInCluster(clusterId); + if (existingHostInCluster != null) { + _hostDao.loadDetails(existingHostInCluster); + } + return existingHostInCluster; + } + @Override public abstract Hypervisor.HypervisorType getHypervisorType(); @@ -422,6 +435,9 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements _kvmGuestNic = _kvmPrivateNic; } + clusterExistingHostCache = new LazyCache<>(32, 15, + this::getExistingHostForCluster); + agentMgr.registerForHostEvents(this, true, false, false); _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; @@ -464,9 +480,8 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements throw new IllegalArgumentException("cannot add host, due to can't find cluster: " + host.getClusterId()); } - HostVO existingHostInCluster = hostDao.findAnyStateHypervisorHostInCluster(clusterVO.getId()); + HostVO existingHostInCluster = clusterExistingHostCache.get(clusterVO.getId()); if (existingHostInCluster != null) { - _hostDao.loadDetails(existingHostInCluster); String hostOsInCluster = existingHostInCluster.getDetail("Host.OS"); String hostOs = ssCmd.getHostDetails().get("Host.OS"); if (!hostOsInCluster.equalsIgnoreCase(hostOs)) { From 33321f00ce65c52cfafe77d53d89e384124c69bf Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 16 Sep 2024 14:28:51 +0530 Subject: [PATCH 29/62] template list fix Signed-off-by: Abhishek Kumar --- .../src/main/java/com/cloud/host/dao/HostDao.java | 2 +- .../main/java/com/cloud/host/dao/HostDaoImpl.java | 6 ++++-- .../com/cloud/storage/dao/VMTemplateDaoImpl.java | 13 ++++--------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java index 5a0af88fb8f..d9a3fb8f18f 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java @@ -175,7 +175,7 @@ public interface HostDao extends GenericDao, StateDao listAllIds(); - List findDistinctHypervisorTypesForZone(final long zoneId); + List listDistinctHypervisorTypes(final Long zoneId); List listAllHostIdsInCluster(final long clusterId); } diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java index c7a0b72e936..1bd51d333f4 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java @@ -1562,14 +1562,16 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao } @Override - public List findDistinctHypervisorTypesForZone(long zoneId) { + public List listDistinctHypervisorTypes(final Long zoneId) { GenericSearchBuilder sb = createSearchBuilder(HypervisorType.class); sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ); sb.select(null, Func.DISTINCT, sb.entity().getHypervisorType()); sb.done(); SearchCriteria sc = sb.create(); - sc.setParameters("zoneId", zoneId); + if (zoneId != null) { + sc.setParameters("zoneId", zoneId); + } sc.setParameters("type", Type.Routing); return customSearch(sc, null); } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java index 7e82b96462d..dd5bc19df5c 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -546,19 +546,14 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem @Override public List listAllReadySystemVMTemplates(Long zoneId) { - List availableHypervisors = null; - if (zoneId != null) { - availableHypervisors = _hostDao.findDistinctHypervisorTypesForZone(zoneId); - if (CollectionUtils.isEmpty(availableHypervisors)) { - return Collections.emptyList(); - } + List availableHypervisors = _hostDao.listDistinctHypervisorTypes(zoneId); + if (CollectionUtils.isEmpty(availableHypervisors)) { + return Collections.emptyList(); } SearchCriteria sc = readySystemTemplateSearch.create(); sc.setParameters("templateType", Storage.TemplateType.SYSTEM); sc.setParameters("state", VirtualMachineTemplate.State.Active); - if (CollectionUtils.isNotEmpty(availableHypervisors)) { - sc.setParameters("hypervisorType", availableHypervisors.toArray()); - } + sc.setParameters("hypervisorType", availableHypervisors.toArray()); sc.setJoinParameters("vmTemplateJoinTemplateStoreRef", "downloadState", List.of(VMTemplateStorageResourceAssoc.Status.DOWNLOADED, VMTemplateStorageResourceAssoc.Status.BYPASSED).toArray()); From 35ed30bd519752aaebce65201b00fb1dcef07a74 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 16 Sep 2024 18:03:06 +0530 Subject: [PATCH 30/62] continuation of 1d47e4d4ae177e4a9f41c12b6d72c0ca011a3f1a list host IDs instead of complete row where possible Signed-off-by: Abhishek Kumar --- .../OutOfBandManagementService.java | 2 +- .../main/java/com/cloud/host/dao/HostDao.java | 17 +++-- .../java/com/cloud/host/dao/HostDaoImpl.java | 71 ++++++++++++------- .../affinity/ExplicitDedicationProcessor.java | 18 ++--- .../DedicatedResourceManagerImpl.java | 41 ++++++----- .../deploy/ImplicitDedicationPlanner.java | 6 +- .../implicitplanner/ImplicitPlannerTest.java | 6 +- .../discoverer/XcpServerDiscoverer.java | 4 +- .../ConfigurationManagerImpl.java | 2 +- .../deploy/DeploymentPlanningManagerImpl.java | 6 +- .../cloud/resource/ResourceManagerImpl.java | 14 ++-- .../cloud/server/ManagementServerImpl.java | 2 +- .../OutOfBandManagementServiceImpl.java | 16 ++--- .../ConfigurationManagerTest.java | 20 +++--- 14 files changed, 123 insertions(+), 102 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementService.java b/api/src/main/java/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementService.java index d670e4d3a88..4f6f1ad66c9 100644 --- a/api/src/main/java/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementService.java +++ b/api/src/main/java/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementService.java @@ -39,7 +39,7 @@ public interface OutOfBandManagementService { long getId(); boolean isOutOfBandManagementEnabled(Host host); void submitBackgroundPowerSyncTask(Host host); - boolean transitionPowerStateToDisabled(List hosts); + boolean transitionPowerStateToDisabled(List hostIds); OutOfBandManagementResponse enableOutOfBandManagement(DataCenter zone); OutOfBandManagementResponse enableOutOfBandManagement(Cluster cluster); diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java index d9a3fb8f18f..d47c08822ad 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java @@ -89,26 +89,27 @@ public interface HostDao extends GenericDao, StateDao findByDataCenterId(Long zoneId); + List listIdsByDataCenterId(Long zoneId); + List findByPodId(Long podId); + List listIdsByPodId(Long podId); + List findByClusterId(Long clusterId); + List listIdsByClusterId(Long clusterId); + List findByClusterIdAndEncryptionSupport(Long clusterId); /** * Returns hosts that are 'Up' and 'Enabled' from the given Data Center/Zone */ - List listByDataCenterId(long id); - - /** - * Returns hosts that are from the given Data Center/Zone and at a given state (e.g. Creating, Enabled, Disabled, etc). - */ - List listByDataCenterIdAndState(long id, ResourceState state); + List listEnabledIdsByDataCenterId(long id); /** * Returns hosts that are 'Up' and 'Disabled' from the given Data Center/Zone */ - List listDisabledByDataCenterId(long id); + List listDisabledIdsByDataCenterId(long id); List listByDataCenterIdAndHypervisorType(long zoneId, Hypervisor.HypervisorType hypervisorType); @@ -176,6 +177,4 @@ public interface HostDao extends GenericDao, StateDao listAllIds(); List listDistinctHypervisorTypes(final Long zoneId); - - List listAllHostIdsInCluster(final long clusterId); } diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java index 1bd51d333f4..9841124cc52 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java @@ -110,6 +110,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao protected SearchBuilder GuidSearch; protected SearchBuilder DcSearch; + protected GenericSearchBuilder IdsDcSearch; protected SearchBuilder PodSearch; protected SearchBuilder ClusterSearch; protected SearchBuilder TypeSearch; @@ -283,6 +284,13 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao DcSearch.and("resourceState", DcSearch.entity().getResourceState(), Op.EQ); DcSearch.done(); + IdsDcSearch = createSearchBuilder(Long.class); + IdsDcSearch.and("zoneId", IdsDcSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + IdsDcSearch.and("resourceState", IdsDcSearch.entity().getResourceState(), SearchCriteria.Op.EQ); + IdsDcSearch.and("status", IdsDcSearch.entity().getStatus(), Op.EQ); + IdsDcSearch.and("type", IdsDcSearch.entity().getType(), SearchCriteria.Op.EQ); + IdsDcSearch.done(); + ClusterStatusSearch = createSearchBuilder(); ClusterStatusSearch.and("cluster", ClusterStatusSearch.entity().getClusterId(), SearchCriteria.Op.EQ); ClusterStatusSearch.and("status", ClusterStatusSearch.entity().getStatus(), SearchCriteria.Op.EQ); @@ -533,29 +541,23 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao return cpuSockets; } - @Override - public List listByDataCenterId(long id) { - return listByDataCenterIdAndState(id, ResourceState.Enabled); - } - - @Override - public List listByDataCenterIdAndState(long id, ResourceState state) { - SearchCriteria sc = scHostsFromZoneUpRouting(id); + private List listIdsByDataCenterIdAndResourceState(long id, ResourceState state) { + SearchCriteria sc = IdsDcSearch.create(); + sc.setParameters("zoneId", id); sc.setParameters("resourceState", state); - return listBy(sc); + sc.setParameters("status", Status.Up); + sc.setParameters("type", Type.Routing); + return customSearch(sc, null); } @Override - public List listDisabledByDataCenterId(long id) { - return listByDataCenterIdAndState(id, ResourceState.Disabled); + public List listEnabledIdsByDataCenterId(long id) { + return listIdsByDataCenterIdAndResourceState(id, ResourceState.Enabled); } - private SearchCriteria scHostsFromZoneUpRouting(long id) { - SearchCriteria sc = DcSearch.create(); - sc.setParameters("dc", id); - sc.setParameters("status", Status.Up); - sc.setParameters("type", Host.Type.Routing); - return sc; + @Override + public List listDisabledIdsByDataCenterId(long id) { + return listIdsByDataCenterIdAndResourceState(id, ResourceState.Disabled); } @Override @@ -1190,6 +1192,14 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao return listBy(sc); } + @Override + public List listIdsByDataCenterId(Long zoneId) { + SearchCriteria sc = IdsDcSearch.create(); + sc.setParameters("dc", zoneId); + sc.setParameters("type", Type.Routing); + return customSearch(sc, null); + } + @Override public List findByPodId(Long podId) { SearchCriteria sc = PodSearch.create(); @@ -1197,6 +1207,16 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao return listBy(sc); } + @Override + public List listIdsByPodId(Long podId) { + GenericSearchBuilder sb = createSearchBuilder(Long.class); + sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); + sb.done(); + SearchCriteria sc = sb.create(); + sc.setParameters("podId", podId); + return customSearch(sc, null); + } + @Override public List findByClusterId(Long clusterId) { SearchCriteria sc = ClusterSearch.create(); @@ -1204,6 +1224,16 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao return listBy(sc); } + @Override + public List listIdsByClusterId(Long clusterId) { + GenericSearchBuilder sb = createSearchBuilder(Long.class); + sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); + sb.done(); + SearchCriteria sc = sb.create(); + sc.setParameters("clusterId", clusterId); + return customSearch(sc, null); + } + @Override public List findByClusterIdAndEncryptionSupport(Long clusterId) { SearchBuilder hostCapabilitySearch = _detailsDao.createSearchBuilder(); @@ -1575,11 +1605,4 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao sc.setParameters("type", Type.Routing); return customSearch(sc, null); } - - @Override - public List listAllHostIdsInCluster(final long clusterId) { - SearchCriteria sc = HostIdSearch.create(); - sc.setParameters("clusterId", clusterId); - return customSearch(sc, null); - } } diff --git a/plugins/affinity-group-processors/explicit-dedication/src/main/java/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java b/plugins/affinity-group-processors/explicit-dedication/src/main/java/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java index 8070a7409b5..e9efda3bc72 100644 --- a/plugins/affinity-group-processors/explicit-dedication/src/main/java/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java +++ b/plugins/affinity-group-processors/explicit-dedication/src/main/java/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java @@ -323,13 +323,13 @@ public class ExplicitDedicationProcessor extends AffinityProcessorBase implement } } //add all hosts inside this in includeList - List hostList = _hostDao.listByDataCenterId(dr.getDataCenterId()); - for (HostVO host : hostList) { - DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId()); + List hostList = _hostDao.listEnabledIdsByDataCenterId(dr.getDataCenterId()); + for (Long hostId : hostList) { + DedicatedResourceVO dHost = _dedicatedDao.findByHostId(hostId); if (dHost != null && !dedicatedResources.contains(dHost)) { - avoidList.addHost(host.getId()); + avoidList.addHost(hostId); } else { - includeList.addHost(host.getId()); + includeList.addHost(hostId); } } } @@ -339,7 +339,7 @@ public class ExplicitDedicationProcessor extends AffinityProcessorBase implement List pods = _podDao.listByDataCenterId(dc.getId()); List clusters = _clusterDao.listClustersByDcId(dc.getId()); - List hosts = _hostDao.listByDataCenterId(dc.getId()); + List hostIds = _hostDao.listEnabledIdsByDataCenterId(dc.getId()); Set podsInIncludeList = includeList.getPodsToAvoid(); Set clustersInIncludeList = includeList.getClustersToAvoid(); Set hostsInIncludeList = includeList.getHostsToAvoid(); @@ -359,9 +359,9 @@ public class ExplicitDedicationProcessor extends AffinityProcessorBase implement } } - for (HostVO host : hosts) { - if (hostsInIncludeList != null && !hostsInIncludeList.contains(host.getId())) { - avoidList.addHost(host.getId()); + for (Long hostId : hostIds) { + if (hostsInIncludeList != null && !hostsInIncludeList.contains(hostId)) { + avoidList.addHost(hostId); } } return avoidList; diff --git a/plugins/dedicated-resources/src/main/java/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java b/plugins/dedicated-resources/src/main/java/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java index cd6d8cf590d..05acbcddd76 100644 --- a/plugins/dedicated-resources/src/main/java/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java +++ b/plugins/dedicated-resources/src/main/java/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java @@ -124,7 +124,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService { @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Zone") public List dedicateZone(final Long zoneId, final Long domainId, final String accountName) { Long accountId = null; - List hosts = null; + List hostIds = null; if (accountName != null) { Account caller = CallContext.current().getCallingAccount(); Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null); @@ -201,17 +201,19 @@ public class DedicatedResourceManagerImpl implements DedicatedService { releaseDedicatedResource(null, null, dr.getClusterId(), null); } - hosts = _hostDao.listByDataCenterId(dc.getId()); - for (HostVO host : hosts) { - DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId()); + hostIds = _hostDao.listEnabledIdsByDataCenterId(dc.getId()); + for (Long hostId : hostIds) { + DedicatedResourceVO dHost = _dedicatedDao.findByHostId(hostId); if (dHost != null) { if (!(childDomainIds.contains(dHost.getDomainId()))) { + HostVO host = _hostDao.findById(hostId); throw new CloudRuntimeException("Host " + host.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain"); } if (accountId != null) { if (dHost.getAccountId().equals(accountId)) { hostsToRelease.add(dHost); } else { + HostVO host = _hostDao.findById(hostId); s_logger.error("Host " + host.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain"); throw new CloudRuntimeException("Host " + host.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain"); } @@ -228,7 +230,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService { } } - checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts); + checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hostIds); final Long accountIdFinal = accountId; return Transaction.execute(new TransactionCallback>() { @@ -282,7 +284,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService { childDomainIds.add(domainId); checkAccountAndDomain(accountId, domainId); HostPodVO pod = _podDao.findById(podId); - List hosts = null; + List hostIds = null; if (pod == null) { throw new InvalidParameterValueException("Unable to find pod by id " + podId); } else { @@ -337,17 +339,19 @@ public class DedicatedResourceManagerImpl implements DedicatedService { releaseDedicatedResource(null, null, dr.getClusterId(), null); } - hosts = _hostDao.findByPodId(pod.getId()); - for (HostVO host : hosts) { - DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId()); + hostIds = _hostDao.listIdsByPodId(pod.getId()); + for (Long hostId : hostIds) { + DedicatedResourceVO dHost = _dedicatedDao.findByHostId(hostId); if (dHost != null) { if (!(getDomainChildIds(domainId).contains(dHost.getDomainId()))) { + HostVO host = _hostDao.findById(hostId); throw new CloudRuntimeException("Host " + host.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain"); } if (accountId != null) { if (dHost.getAccountId().equals(accountId)) { hostsToRelease.add(dHost); } else { + HostVO host = _hostDao.findById(hostId); s_logger.error("Host " + host.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain"); throw new CloudRuntimeException("Host " + host.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain"); } @@ -364,7 +368,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService { } } - checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts); + checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hostIds); final Long accountIdFinal = accountId; return Transaction.execute(new TransactionCallback>() { @@ -400,7 +404,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService { @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Cluster") public List dedicateCluster(final Long clusterId, final Long domainId, final String accountName) { Long accountId = null; - List hosts = null; + List hostIds = null; if (accountName != null) { Account caller = CallContext.current().getCallingAccount(); Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null); @@ -446,12 +450,13 @@ public class DedicatedResourceManagerImpl implements DedicatedService { } //check if any resource under this cluster is dedicated to different account or sub-domain - hosts = _hostDao.findByClusterId(cluster.getId()); + hostIds = _hostDao.listIdsByClusterId(cluster.getId()); List hostsToRelease = new ArrayList(); - for (HostVO host : hosts) { - DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId()); + for (Long hostId : hostIds) { + DedicatedResourceVO dHost = _dedicatedDao.findByHostId(hostId); if (dHost != null) { if (!(childDomainIds.contains(dHost.getDomainId()))) { + HostVO host = _hostDao.findById(hostId); throw new CloudRuntimeException("Host " + host.getName() + " under this Cluster " + cluster.getName() + " is dedicated to different account/domain"); } @@ -477,7 +482,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService { } } - checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts); + checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hostIds); final Long accountIdFinal = accountId; return Transaction.execute(new TransactionCallback>() { @@ -682,10 +687,10 @@ public class DedicatedResourceManagerImpl implements DedicatedService { return suitable; } - private boolean checkHostsSuitabilityForExplicitDedication(Long accountId, List domainIds, List hosts) { + private boolean checkHostsSuitabilityForExplicitDedication(Long accountId, List domainIds, List hostIds) { boolean suitable = true; - for (HostVO host : hosts) { - checkHostSuitabilityForExplicitDedication(accountId, domainIds, host.getId()); + for (Long hostId : hostIds) { + checkHostSuitabilityForExplicitDedication(accountId, domainIds, hostId); } return suitable; } diff --git a/plugins/deployment-planners/implicit-dedication/src/main/java/com/cloud/deploy/ImplicitDedicationPlanner.java b/plugins/deployment-planners/implicit-dedication/src/main/java/com/cloud/deploy/ImplicitDedicationPlanner.java index d6cd328b454..603b893829c 100644 --- a/plugins/deployment-planners/implicit-dedication/src/main/java/com/cloud/deploy/ImplicitDedicationPlanner.java +++ b/plugins/deployment-planners/implicit-dedication/src/main/java/com/cloud/deploy/ImplicitDedicationPlanner.java @@ -78,7 +78,7 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy List allHosts = new ArrayList<>(); if (CollectionUtils.isNotEmpty(clusterList)) { allHosts = clusterList.stream() - .flatMap(cluster -> hostDao.listAllHostIdsInCluster(cluster).stream()) + .flatMap(cluster -> hostDao.listIdsByClusterId(cluster).stream()) .collect(Collectors.toList()); } @@ -227,7 +227,7 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy } return clusterList.stream() .filter(cluster -> { - Set hostsInClusterSet = new HashSet<>(hostDao.listAllHostIdsInCluster(cluster)); + Set hostsInClusterSet = new HashSet<>(hostDao.listIdsByClusterId(cluster)); return !hostsSet.containsAll(hostsInClusterSet); }) .collect(Collectors.toList()); @@ -253,7 +253,7 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy List allHosts = new ArrayList<>(); if (CollectionUtils.isNotEmpty(clusterList)) { allHosts = clusterList.stream() - .flatMap(cluster -> hostDao.listAllHostIdsInCluster(cluster).stream()) + .flatMap(cluster -> hostDao.listIdsByClusterId(cluster).stream()) .collect(Collectors.toList()); } // Go over all the hosts in the cluster and get a list of diff --git a/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java b/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java index a18f2f39a8d..55222b6ca84 100644 --- a/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java +++ b/plugins/deployment-planners/implicit-dedication/src/test/java/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java @@ -385,9 +385,9 @@ public class ImplicitPlannerTest { when(serviceOfferingDetailsDao.listDetailsKeyPairs(offeringId)).thenReturn(details); // Initialize hosts in clusters - when(hostDao.listAllHostIdsInCluster(1)).thenReturn(List.of(5L)); - when(hostDao.listAllHostIdsInCluster(2)).thenReturn(List.of(6L)); - when(hostDao.listAllHostIdsInCluster(3)).thenReturn(List.of(7L)); + when(hostDao.listIdsByClusterId(1L)).thenReturn(List.of(5L)); + when(hostDao.listIdsByClusterId(2L)).thenReturn(List.of(6L)); + when(hostDao.listIdsByClusterId(3L)).thenReturn(List.of(7L)); // Mock vms on each host. long offeringIdForVmsOfThisAccount = 15L; diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java index da2c305b74e..1a321ba0991 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java @@ -147,7 +147,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L sc.and(sc.entity().getGuid(), Op.EQ, guid); List clusters = sc.list(); ClusterVO clu = clusters.get(0); - List clusterHostIds = _hostDao.listAllHostIdsInCluster(clu.getId()); + List clusterHostIds = _hostDao.listIdsByClusterId(clu.getId()); if (CollectionUtils.isEmpty(clusterHostIds)) { clu.setGuid(null); _clusterDao.update(clu.getId(), clu); @@ -248,7 +248,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L if (clu.getGuid() == null) { setClusterGuid(clu, poolUuid); } else { - List clusterHostIds = _hostDao.listAllHostIdsInCluster(clusterId); + List clusterHostIds = _hostDao.listIdsByClusterId(clusterId); if (CollectionUtils.isNotEmpty(clusterHostIds)) { if (!clu.getGuid().equals(poolUuid)) { String msg = "Please join the host " + hostIp + " to XS pool " diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index 04516d4304a..d6673ef5b3b 100644 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -2350,7 +2350,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // Check if there are any non-removed hosts in the zone. - if (!_hostDao.listByDataCenterId(zoneId).isEmpty()) { + if (!_hostDao.listEnabledIdsByDataCenterId(zoneId).isEmpty()) { throw new CloudRuntimeException(errorMsg + "there are servers in this zone."); } diff --git a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java index a86bdd0fea6..d6f32d2f962 100644 --- a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -649,10 +649,8 @@ StateListener, Configurable { * Adds disabled Hosts to the ExcludeList in order to avoid them at the deployment planner. */ protected void avoidDisabledHosts(DataCenter dc, ExcludeList avoids) { - List disabledHosts = _hostDao.listDisabledByDataCenterId(dc.getId()); - for (HostVO host : disabledHosts) { - avoids.addHost(host.getId()); - } + List disabledHostIds = _hostDao.listDisabledIdsByDataCenterId(dc.getId()); + disabledHostIds.forEach(avoids::addHost); } /** diff --git a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java index 6aa733a9a50..f9189d2ff52 100755 --- a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java @@ -643,7 +643,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, throw ex; } else { if (cluster.getGuid() == null) { - final List hostIds = _hostDao.listAllHostIdsInCluster(clusterId); + final List hostIds = _hostDao.listIdsByClusterId(clusterId); if (!hostIds.isEmpty()) { final CloudRuntimeException ex = new CloudRuntimeException("Guid is not updated for cluster with specified cluster id; need to wait for hosts in this cluster to come up"); @@ -962,7 +962,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, Host hostRemoved = _hostDao.findById(hostId); _hostDao.remove(hostId); if (clusterId != null) { - final List hostIds = _hostDao.listAllHostIdsInCluster(clusterId); + final List hostIds = _hostDao.listIdsByClusterId(clusterId); if (CollectionUtils.isEmpty(hostIds)) { final ClusterVO cluster = _clusterDao.findById(clusterId); cluster.setGuid(null); @@ -1087,7 +1087,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, final Hypervisor.HypervisorType hypervisorType = cluster.getHypervisorType(); - final List hostIds = _hostDao.listAllHostIdsInCluster(cmd.getId()); + final List hostIds = _hostDao.listIdsByClusterId(cmd.getId()); if (!hostIds.isEmpty()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Cluster: " + cmd.getId() + " still has hosts, can't remove"); @@ -2425,10 +2425,10 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, boolean clusterSupportsResigning = true; - List hostVOs = _hostDao.findByClusterId(host.getClusterId()); + List hostIds = _hostDao.listIdsByClusterId(host.getClusterId()); - for (HostVO hostVO : hostVOs) { - DetailVO hostDetailVO = _hostDetailsDao.findDetail(hostVO.getId(), name); + for (Long hostId : hostIds) { + DetailVO hostDetailVO = _hostDetailsDao.findDetail(hostId, name); if (hostDetailVO == null || Boolean.parseBoolean(hostDetailVO.getValue()) == false) { clusterSupportsResigning = false; @@ -3034,7 +3034,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, public boolean updateClusterPassword(final UpdateHostPasswordCmd command) { final boolean shouldUpdateHostPasswd = command.getUpdatePasswdOnHost(); // get agents for the cluster - final List hostIds = _hostDao.listAllHostIdsInCluster(command.getClusterId()); + final List hostIds = _hostDao.listIdsByClusterId(command.getClusterId()); for (final Long hostId : hostIds) { try { final Boolean result = propagateResourceEvent(hostId, ResourceState.Event.UpdatePassword); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 81422e3dbf9..1ac0bc537ce 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -4860,7 +4860,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private boolean updateHostsInCluster(final UpdateHostPasswordCmd command) { // get all the hosts in this cluster - final List hostIds = _hostDao.listAllHostIdsInCluster(command.getClusterId()); + final List hostIds = _hostDao.listIdsByClusterId(command.getClusterId()); String userNameWithoutSpaces = StringUtils.deleteWhitespace(command.getUsername()); if (StringUtils.isBlank(userNameWithoutSpaces)) { diff --git a/server/src/main/java/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceImpl.java b/server/src/main/java/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceImpl.java index 302765aa287..b2d49e6f26b 100644 --- a/server/src/main/java/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceImpl.java +++ b/server/src/main/java/org/apache/cloudstack/outofbandmanagement/OutOfBandManagementServiceImpl.java @@ -285,11 +285,11 @@ public class OutOfBandManagementServiceImpl extends ManagerBase implements OutOf && isOutOfBandManagementEnabledForHost(host.getId()); } - public boolean transitionPowerStateToDisabled(List hosts) { + public boolean transitionPowerStateToDisabled(List hostIds) { boolean result = true; - for (Host host : hosts) { + for (Long hostId : hostIds) { result = result && transitionPowerState(OutOfBandManagement.PowerState.Event.Disabled, - outOfBandManagementDao.findByHost(host.getId())); + outOfBandManagementDao.findByHost(hostId)); } return result; } @@ -318,7 +318,7 @@ public class OutOfBandManagementServiceImpl extends ManagerBase implements OutOf @ActionEvent(eventType = EventTypes.EVENT_HOST_OUTOFBAND_MANAGEMENT_DISABLE, eventDescription = "disabling out-of-band management on a zone") public OutOfBandManagementResponse disableOutOfBandManagement(final DataCenter zone) { dataCenterDetailsDao.persist(zone.getId(), OOBM_ENABLED_DETAIL, String.valueOf(false)); - transitionPowerStateToDisabled(hostDao.findByDataCenterId(zone.getId())); + transitionPowerStateToDisabled(hostDao.listIdsByDataCenterId(zone.getId())); return buildEnableDisableResponse(false); } @@ -334,7 +334,7 @@ public class OutOfBandManagementServiceImpl extends ManagerBase implements OutOf @ActionEvent(eventType = EventTypes.EVENT_HOST_OUTOFBAND_MANAGEMENT_DISABLE, eventDescription = "disabling out-of-band management on a cluster") public OutOfBandManagementResponse disableOutOfBandManagement(final Cluster cluster) { clusterDetailsDao.persist(cluster.getId(), OOBM_ENABLED_DETAIL, String.valueOf(false)); - transitionPowerStateToDisabled(hostDao.findByClusterId(cluster.getId())); + transitionPowerStateToDisabled(hostDao.listIdsByClusterId(cluster.getId())); return buildEnableDisableResponse(false); } @@ -354,7 +354,7 @@ public class OutOfBandManagementServiceImpl extends ManagerBase implements OutOf outOfBandManagementConfig.setEnabled(true); boolean updateResult = outOfBandManagementDao.update(outOfBandManagementConfig.getId(), (OutOfBandManagementVO) outOfBandManagementConfig); if (updateResult) { - transitionPowerStateToDisabled(Collections.singletonList(host)); + transitionPowerStateToDisabled(Collections.singletonList(host.getId())); } return buildEnableDisableResponse(true); } @@ -367,7 +367,7 @@ public class OutOfBandManagementServiceImpl extends ManagerBase implements OutOf outOfBandManagementConfig.setEnabled(false); boolean updateResult = outOfBandManagementDao.update(outOfBandManagementConfig.getId(), (OutOfBandManagementVO) outOfBandManagementConfig); if (updateResult) { - transitionPowerStateToDisabled(Collections.singletonList(host)); + transitionPowerStateToDisabled(Collections.singletonList(host.getId())); } return buildEnableDisableResponse(false); } @@ -578,7 +578,7 @@ public class OutOfBandManagementServiceImpl extends ManagerBase implements OutOf if (isOutOfBandManagementEnabled(host)) { submitBackgroundPowerSyncTask(host); } else if (outOfBandManagementHost.getPowerState() != OutOfBandManagement.PowerState.Disabled) { - if (transitionPowerStateToDisabled(Collections.singletonList(host))) { + if (transitionPowerStateToDisabled(Collections.singletonList(host.getId()))) { if (LOG.isDebugEnabled()) { LOG.debug(String.format("Out-of-band management was disabled in zone/cluster/host, disabled power state for %s", host)); } diff --git a/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java b/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java index 715924d5c54..a1d32eee673 100644 --- a/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java +++ b/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java @@ -733,7 +733,7 @@ public class ConfigurationManagerTest { @Test public void checkIfZoneIsDeletableSuccessTest() { - Mockito.when(_hostDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); + Mockito.when(_hostDao.listEnabledIdsByDataCenterId(anyLong())).thenReturn(new ArrayList<>()); Mockito.when(_podDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); Mockito.when(_privateIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); Mockito.when(_publicIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); @@ -747,11 +747,7 @@ public class ConfigurationManagerTest { @Test(expected = CloudRuntimeException.class) public void checkIfZoneIsDeletableFailureOnHostTest() { - HostVO hostVO = Mockito.mock(HostVO.class); - ArrayList arrayList = new ArrayList(); - arrayList.add(hostVO); - - Mockito.when(_hostDao.listByDataCenterId(anyLong())).thenReturn(arrayList); + Mockito.when(_hostDao.listEnabledIdsByDataCenterId(anyLong())).thenReturn(List.of(1L)); Mockito.when(_podDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); Mockito.when(_privateIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); Mockito.when(_publicIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); @@ -769,7 +765,7 @@ public class ConfigurationManagerTest { ArrayList arrayList = new ArrayList(); arrayList.add(hostPodVO); - Mockito.when(_hostDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); + Mockito.when(_hostDao.listEnabledIdsByDataCenterId(anyLong())).thenReturn(new ArrayList<>()); Mockito.when(_podDao.listByDataCenterId(anyLong())).thenReturn(arrayList); Mockito.when(_privateIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); Mockito.when(_publicIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); @@ -783,7 +779,7 @@ public class ConfigurationManagerTest { @Test(expected = CloudRuntimeException.class) public void checkIfZoneIsDeletableFailureOnPrivateIpAddressTest() { - Mockito.when(_hostDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); + Mockito.when(_hostDao.listEnabledIdsByDataCenterId(anyLong())).thenReturn(new ArrayList<>()); Mockito.when(_podDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); Mockito.when(_privateIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(1); Mockito.when(_publicIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); @@ -797,7 +793,7 @@ public class ConfigurationManagerTest { @Test(expected = CloudRuntimeException.class) public void checkIfZoneIsDeletableFailureOnPublicIpAddressTest() { - Mockito.when(_hostDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); + Mockito.when(_hostDao.listEnabledIdsByDataCenterId(anyLong())).thenReturn(new ArrayList<>()); Mockito.when(_podDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); Mockito.when(_privateIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); Mockito.when(_publicIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(1); @@ -815,7 +811,7 @@ public class ConfigurationManagerTest { ArrayList arrayList = new ArrayList(); arrayList.add(vMInstanceVO); - Mockito.when(_hostDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); + Mockito.when(_hostDao.listEnabledIdsByDataCenterId(anyLong())).thenReturn(new ArrayList<>()); Mockito.when(_podDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); Mockito.when(_privateIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); Mockito.when(_publicIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); @@ -833,7 +829,7 @@ public class ConfigurationManagerTest { ArrayList arrayList = new ArrayList(); arrayList.add(volumeVO); - Mockito.when(_hostDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); + Mockito.when(_hostDao.listEnabledIdsByDataCenterId(anyLong())).thenReturn(new ArrayList<>()); Mockito.when(_podDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); Mockito.when(_privateIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); Mockito.when(_publicIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); @@ -851,7 +847,7 @@ public class ConfigurationManagerTest { ArrayList arrayList = new ArrayList(); arrayList.add(physicalNetworkVO); - Mockito.when(_hostDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); + Mockito.when(_hostDao.listEnabledIdsByDataCenterId(anyLong())).thenReturn(new ArrayList<>()); Mockito.when(_podDao.listByDataCenterId(anyLong())).thenReturn(new ArrayList()); Mockito.when(_privateIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); Mockito.when(_publicIpAddressDao.countIPs(anyLong(), anyBoolean())).thenReturn(0); From 8941fa550caac5e8b4f5cbd19a87d2c15fe1a3a9 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 17 Sep 2024 15:50:14 +0530 Subject: [PATCH 31/62] build fix Signed-off-by: Abhishek Kumar --- .../CreateNetworkOfferingTest.java | 48 +++++------- .../test/resources/createNetworkOffering.xml | 76 ------------------- 2 files changed, 19 insertions(+), 105 deletions(-) delete mode 100644 server/src/test/resources/createNetworkOffering.xml diff --git a/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java b/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java index 72bd7bb0cd8..4f7e04ac552 100644 --- a/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java +++ b/server/src/test/java/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.networkoffering; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.nullable; import java.util.HashMap; @@ -26,22 +25,21 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import javax.inject.Inject; - import org.apache.cloudstack.annotation.dao.AnnotationDao; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.framework.config.impl.ConfigurationVO; import org.apache.cloudstack.resourcedetail.dao.UserIpAddressDetailsDao; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.Mockito; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.mockito.junit.MockitoJUnitRunner; import com.cloud.configuration.ConfigurationManager; +import com.cloud.configuration.ConfigurationManagerImpl; import com.cloud.event.dao.UsageEventDao; import com.cloud.event.dao.UsageEventDetailsDao; import com.cloud.exception.InvalidParameterValueException; @@ -59,60 +57,52 @@ import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; import com.cloud.user.UserVO; -import com.cloud.utils.component.ComponentContext; import com.cloud.vm.dao.UserVmDetailsDao; import junit.framework.TestCase; -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "classpath:/createNetworkOffering.xml") +@RunWith(MockitoJUnitRunner.class) public class CreateNetworkOfferingTest extends TestCase { - @Inject - ConfigurationManager configMgr; - - @Inject + @Mock ConfigurationDao configDao; - @Inject + @Mock NetworkOfferingDao offDao; - @Inject + @Mock NetworkOfferingServiceMapDao mapDao; - @Inject + @Mock AccountManager accountMgr; - @Inject + @Mock VpcManager vpcMgr; - @Inject + @Mock UserVmDetailsDao userVmDetailsDao; - @Inject + @Mock UsageEventDao UsageEventDao; - @Inject + @Mock UsageEventDetailsDao usageEventDetailsDao; - @Inject + @Mock UserIpAddressDetailsDao userIpAddressDetailsDao; - @Inject + @Mock LoadBalancerVMMapDao _loadBalancerVMMapDao; - @Inject + @Mock AnnotationDao annotationDao; + @InjectMocks + ConfigurationManager configMgr = new ConfigurationManagerImpl(); + @Override @Before public void setUp() { - ComponentContext.initComponentsLifeCycle(); - - ConfigurationVO configVO = new ConfigurationVO("200", "200", "200", "200", "200", "200"); - Mockito.when(configDao.findByName(anyString())).thenReturn(configVO); - - Mockito.when(offDao.persist(any(NetworkOfferingVO.class))).thenReturn(new NetworkOfferingVO()); Mockito.when(offDao.persist(any(NetworkOfferingVO.class), nullable(Map.class))).thenReturn(new NetworkOfferingVO()); Mockito.when(mapDao.persist(any(NetworkOfferingServiceMapVO.class))).thenReturn(new NetworkOfferingServiceMapVO()); Mockito.when(accountMgr.getSystemUser()).thenReturn(new UserVO(1)); diff --git a/server/src/test/resources/createNetworkOffering.xml b/server/src/test/resources/createNetworkOffering.xml deleted file mode 100644 index 4242ae6281e..00000000000 --- a/server/src/test/resources/createNetworkOffering.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 0151f125aa95960902e62f81c03cf22cdc9818d6 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 23 Sep 2024 20:04:34 +0530 Subject: [PATCH 32/62] improvement Signed-off-by: Abhishek Kumar --- .../java/com/cloud/vm/dao/VMInstanceDao.java | 6 ++++ .../com/cloud/vm/dao/VMInstanceDaoImpl.java | 33 +++++++++++++++++++ .../resourcedetail/ResourceDetailsDao.java | 2 ++ .../ResourceDetailsDaoBase.java | 15 +++++++++ .../cloud/capacity/CapacityManagerImpl.java | 31 ++++++++++------- 5 files changed, 76 insertions(+), 11 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java index 34da02b216a..a840c422212 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java @@ -170,4 +170,10 @@ public interface VMInstanceDao extends GenericDao, StateDao< List searchRemovedByRemoveDate(final Date startDate, final Date endDate, final Long batchSize, List skippedVmIds); + List listIdServiceOfferingForUpVmsByHostId(Long hostId); + + List listIdServiceOfferingForVmsMigratingFromHost(Long hostId); + + List listIdServiceOfferingForVmsByLastHostId(Long hostId); + } diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java index b85ec931e24..ef436a47d39 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -74,6 +74,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem protected SearchBuilder LHVMClusterSearch; protected SearchBuilder IdStatesSearch; protected SearchBuilder AllFieldsSearch; + protected SearchBuilder IdServiceOfferingIdSelectSearch; protected SearchBuilder ZoneTemplateNonExpungedSearch; protected SearchBuilder TemplateNonExpungedSearch; protected SearchBuilder NameLikeSearch; @@ -171,6 +172,14 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem AllFieldsSearch.and("account", AllFieldsSearch.entity().getAccountId(), Op.EQ); AllFieldsSearch.done(); + IdServiceOfferingIdSelectSearch = createSearchBuilder(); + IdServiceOfferingIdSelectSearch.and("host", IdServiceOfferingIdSelectSearch.entity().getHostId(), Op.EQ); + IdServiceOfferingIdSelectSearch.and("lastHost", IdServiceOfferingIdSelectSearch.entity().getLastHostId(), Op.EQ); + IdServiceOfferingIdSelectSearch.and("state", IdServiceOfferingIdSelectSearch.entity().getState(), Op.EQ); + IdServiceOfferingIdSelectSearch.and("states", IdServiceOfferingIdSelectSearch.entity().getState(), Op.IN); + IdServiceOfferingIdSelectSearch.selectFields(IdServiceOfferingIdSelectSearch.entity().getId(), IdServiceOfferingIdSelectSearch.entity().getServiceOfferingId()); + IdServiceOfferingIdSelectSearch.done(); + ZoneTemplateNonExpungedSearch = createSearchBuilder(); ZoneTemplateNonExpungedSearch.and("zone", ZoneTemplateNonExpungedSearch.entity().getDataCenterId(), Op.EQ); ZoneTemplateNonExpungedSearch.and("template", ZoneTemplateNonExpungedSearch.entity().getTemplateId(), Op.EQ); @@ -1051,4 +1060,28 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem Filter filter = new Filter(VMInstanceVO.class, "id", true, 0L, batchSize); return searchIncludingRemoved(sc, filter, null, false); } + + @Override + public List listIdServiceOfferingForUpVmsByHostId(Long hostId) { + SearchCriteria sc = IdServiceOfferingIdSelectSearch.create(); + sc.setParameters("host", hostId); + sc.setParameters("states", new Object[] {State.Starting, State.Running, State.Stopping, State.Migrating}); + return customSearch(sc, null); + } + + @Override + public List listIdServiceOfferingForVmsMigratingFromHost(Long hostId) { + SearchCriteria sc = IdServiceOfferingIdSelectSearch.create(); + sc.setParameters("lastHost", hostId); + sc.setParameters("state", State.Migrating); + return customSearch(sc, null); + } + + @Override + public List listIdServiceOfferingForVmsByLastHostId(Long hostId) { + SearchCriteria sc = IdServiceOfferingIdSelectSearch.create(); + sc.setParameters("lastHost", hostId); + sc.setParameters("state", State.Stopped); + return customSearch(sc, null); + } } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDao.java b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDao.java index 8f3d264da98..6d0d9378c7c 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDao.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDao.java @@ -88,6 +88,8 @@ public interface ResourceDetailsDao extends GenericDao public Map listDetailsKeyPairs(long resourceId); + Map listDetailsKeyPairs(long resourceId, List keys); + public Map listDetailsKeyPairs(long resourceId, boolean forDisplay); Map listDetailsVisibility(long resourceId); diff --git a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDaoBase.java b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDaoBase.java index 4205a7823e4..f2e156f225a 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDaoBase.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/resourcedetail/ResourceDetailsDaoBase.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.resourcedetail; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.apache.cloudstack.api.ResourceDetail; import org.apache.commons.collections.CollectionUtils; @@ -91,6 +92,20 @@ public abstract class ResourceDetailsDaoBase extends G return details; } + @Override + public Map listDetailsKeyPairs(long resourceId, List keys) { + SearchBuilder sb = createSearchBuilder(); + sb.and("resourceId", sb.entity().getResourceId(), SearchCriteria.Op.EQ); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.IN); + sb.done(); + SearchCriteria sc = sb.create(); + sc.setParameters("resourceId", resourceId); + sc.setParameters("name", keys.toArray()); + + List results = search(sc, null); + return results.stream().collect(Collectors.toMap(R::getName, R::getValue)); + } + public Map listDetailsVisibility(long resourceId) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("resourceId", resourceId); diff --git a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java index e13cc47082b..6caa137c003 100644 --- a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java @@ -684,6 +684,15 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, return serviceOfferingVO; } + protected Map getVmDetailsForCapacityCalculation(long vmId) { + return _userVmDetailsDao.listDetailsKeyPairs(vmId, + List.of(VmDetailConstants.CPU_OVER_COMMIT_RATIO, + VmDetailConstants.MEMORY_OVER_COMMIT_RATIO, + UsageEventVO.DynamicParameters.memory.name(), + UsageEventVO.DynamicParameters.cpuNumber.name(), + UsageEventVO.DynamicParameters.cpuSpeed.name())); + } + @DB protected void updateCapacityForHostInternal(final Host host) { long usedCpuCore = 0; @@ -694,12 +703,12 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, long reservedCpu = 0; final CapacityState capacityState = (host.getResourceState() == ResourceState.Enabled) ? CapacityState.Enabled : CapacityState.Disabled; - List vms = _vmDao.listUpByHostId(host.getId()); + List vms = _vmDao.listIdServiceOfferingForUpVmsByHostId(host.getId()); if (s_logger.isDebugEnabled()) { s_logger.debug("Found " + vms.size() + " VMs on host " + host.getId()); } - final List vosMigrating = _vmDao.listVmsMigratingFromHost(host.getId()); + final List vosMigrating = _vmDao.listIdServiceOfferingForVmsMigratingFromHost(host.getId()); if (s_logger.isDebugEnabled()) { s_logger.debug("Found " + vosMigrating.size() + " VMs are Migrating from host " + host.getId()); } @@ -714,9 +723,9 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, for (VMInstanceVO vm : vms) { Float cpuOvercommitRatio = 1.0f; Float ramOvercommitRatio = 1.0f; - Map vmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId()); - String vmDetailCpu = vmDetails.get("cpuOvercommitRatio"); - String vmDetailRam = vmDetails.get("memoryOvercommitRatio"); + Map vmDetails = getVmDetailsForCapacityCalculation(vm.getId()); + String vmDetailCpu = vmDetails.get(VmDetailConstants.CPU_OVER_COMMIT_RATIO); + String vmDetailRam = vmDetails.get(VmDetailConstants.MEMORY_OVER_COMMIT_RATIO); // if vmDetailCpu or vmDetailRam is not null it means it is running in a overcommitted cluster. cpuOvercommitRatio = (vmDetailCpu != null) ? Float.parseFloat(vmDetailCpu) : clusterCpuOvercommitRatio; ramOvercommitRatio = (vmDetailRam != null) ? Float.parseFloat(vmDetailRam) : clusterRamOvercommitRatio; @@ -745,7 +754,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, } } - List vmsByLastHostId = _vmDao.listByLastHostId(host.getId()); + List vmsByLastHostId = _vmDao.listIdServiceOfferingForVmsByLastHostId(host.getId()); if (s_logger.isDebugEnabled()) { s_logger.debug("Found " + vmsByLastHostId.size() + " VM, not running on host " + host.getId()); } @@ -756,17 +765,17 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, long lastModificationTime = Optional.ofNullable(vm.getUpdateTime()).orElse(vm.getCreated()).getTime(); long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - lastModificationTime) / 1000; if (secondsSinceLastUpdate < _vmCapacityReleaseInterval) { - UserVmDetailVO vmDetailCpu = _userVmDetailsDao.findDetail(vm.getId(), VmDetailConstants.CPU_OVER_COMMIT_RATIO); - UserVmDetailVO vmDetailRam = _userVmDetailsDao.findDetail(vm.getId(), VmDetailConstants.MEMORY_OVER_COMMIT_RATIO); + Map vmDetails = getVmDetailsForCapacityCalculation(vm.getId()); + String vmDetailCpu = vmDetails.get(VmDetailConstants.CPU_OVER_COMMIT_RATIO); + String vmDetailRam = vmDetails.get(VmDetailConstants.MEMORY_OVER_COMMIT_RATIO); if (vmDetailCpu != null) { //if vmDetail_cpu is not null it means it is running in a overcommited cluster. - cpuOvercommitRatio = Float.parseFloat(vmDetailCpu.getValue()); + cpuOvercommitRatio = Float.parseFloat(vmDetailCpu); } if (vmDetailRam != null) { - ramOvercommitRatio = Float.parseFloat(vmDetailRam.getValue()); + ramOvercommitRatio = Float.parseFloat(vmDetailRam); } ServiceOffering so = getServiceOffering(vm.getServiceOfferingId()); - Map vmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId()); if (so == null) { so = _offeringsDao.findByIdIncludingRemoved(vm.getServiceOfferingId()); } From 1652086ff9d777f04fa09658e33e5545e69367b1 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 25 Sep 2024 18:33:55 +0530 Subject: [PATCH 33/62] wip changes for agent reconnection Signed-off-by: Abhishek Kumar --- .../src/main/java/com/cloud/agent/Agent.java | 14 ++- .../cloud/agent/manager/AgentManagerImpl.java | 16 ++- .../main/java/com/cloud/utils/nio/Link.java | 12 +- .../java/com/cloud/utils/nio/NioClient.java | 11 +- .../com/cloud/utils/nio/NioConnection.java | 113 +++++++++++------- .../java/com/cloud/utils/nio/NioServer.java | 3 +- .../com/cloud/utils/testcase/NioTest.java | 2 +- 7 files changed, 107 insertions(+), 64 deletions(-) diff --git a/agent/src/main/java/com/cloud/agent/Agent.java b/agent/src/main/java/com/cloud/agent/Agent.java index 9e0ee746c03..eb584aaf2d9 100644 --- a/agent/src/main/java/com/cloud/agent/Agent.java +++ b/agent/src/main/java/com/cloud/agent/Agent.java @@ -154,6 +154,14 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater private String _keystoreSetupPath; private String _keystoreCertImportPath; + protected String getConnectionName() { + return "Agent-" + _resource.getName(); + } + + protected String getConnectionNameLog() { + return String.format("%s:: ", getConnectionName()); + } + // for simulator use only public Agent(final IAgentShell shell) { _shell = shell; @@ -195,7 +203,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater } final String host = _shell.getNextHost(); - _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this); + _connection = new NioClient(getConnectionName(), host, _shell.getPort(), _shell.getWorkers(), this); // ((NioClient)_connection).setBindAddress(_shell.getPrivateIp()); @@ -536,7 +544,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater _resource.disconnected(); - s_logger.info("Lost connection to host: " + _shell.getConnectedHost() + ". Attempting reconnection while we still have " + _inProgress.get() + " commands in progress."); + s_logger.info(getConnectionNameLog() + "Lost connection to host: " + _shell.getConnectedHost() + ". Attempting reconnection while we still have " + _inProgress.get() + " commands in progress."); _connection.stop(); @@ -553,7 +561,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater do { final String host = _shell.getNextHost(); _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this); - s_logger.info("Reconnecting to host:" + host); + s_logger.info(getConnectionNameLog() + "Reconnecting to host:" + host); try { _connection.start(); } catch (final NioConnectionException e) { diff --git a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java index 6f9db09693c..8d0e0b09780 100644 --- a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java @@ -38,9 +38,6 @@ import java.util.concurrent.locks.ReentrantLock; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.configuration.Config; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.db.GlobalLock; import org.apache.cloudstack.agent.lb.IndirectAgentLB; import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; @@ -53,6 +50,7 @@ import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.outofbandmanagement.dao.OutOfBandManagementDao; import org.apache.cloudstack.utils.identity.ManagementServerNode; import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.apache.log4j.MDC; @@ -81,6 +79,7 @@ import com.cloud.agent.api.UnsupportedAnswer; import com.cloud.agent.transport.Request; import com.cloud.agent.transport.Response; import com.cloud.alert.AlertManager; +import com.cloud.configuration.Config; import com.cloud.configuration.ManagementServiceConfiguration; import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenterVO; @@ -104,11 +103,13 @@ import com.cloud.resource.Discoverer; import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceState; import com.cloud.resource.ServerResource; +import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.EntityManager; +import com.cloud.utils.db.GlobalLock; import com.cloud.utils.db.QueryBuilder; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.TransactionLegacy; @@ -123,7 +124,6 @@ import com.cloud.utils.nio.Link; import com.cloud.utils.nio.NioServer; import com.cloud.utils.nio.Task; import com.cloud.utils.time.InaccurateClock; -import org.apache.commons.lang3.StringUtils; /** * Implementation of the Agent Manager. This class controls the connection to the agents. @@ -197,6 +197,8 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl protected final ConfigKey Workers = new ConfigKey("Advanced", Integer.class, "workers", "5", "Number of worker threads handling remote agent connections.", false); protected final ConfigKey Port = new ConfigKey("Advanced", Integer.class, "port", "8250", "Port to listen on for remote agent connections.", false); + protected final ConfigKey RemoteAgentSslHandshakeTimeout = new ConfigKey<>("Advanced", Integer.class, "agent.ssl.handshake.timeout", "30", + "Seconds after which SSL handshake times out during remote agent connections.", false); protected final ConfigKey AlertWait = new ConfigKey("Advanced", Integer.class, "alert.wait", "1800", "Seconds to wait before alerting on a disconnected agent", true); protected final ConfigKey DirectAgentLoadSize = new ConfigKey("Advanced", Integer.class, "direct.agent.load.size", "16", @@ -231,7 +233,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl // allow core threads to time out even when there are no items in the queue _connectExecutor.allowCoreThreadTimeOut(true); - _connection = new NioServer("AgentManager", Port.value(), Workers.value() + 10, this, caService); + _connection = new NioServer("AgentManager", Port.value(), Workers.value() + 10, this, caService, RemoteAgentSslHandshakeTimeout.value()); s_logger.info("Listening on " + Port.value() + " with " + Workers.value() + " workers"); // executes all agent commands other than cron and ping @@ -1838,7 +1840,9 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl @Override public ConfigKey[] getConfigKeys() { return new ConfigKey[] { CheckTxnBeforeSending, Workers, Port, Wait, AlertWait, DirectAgentLoadSize, - DirectAgentPoolSize, DirectAgentThreadCap, EnableKVMAutoEnableDisable, ReadyCommandWait }; + DirectAgentPoolSize, DirectAgentThreadCap, EnableKVMAutoEnableDisable, ReadyCommandWait, + RemoteAgentSslHandshakeTimeout + }; } protected class SetHostParamsListener implements Listener { diff --git a/utils/src/main/java/com/cloud/utils/nio/Link.java b/utils/src/main/java/com/cloud/utils/nio/Link.java index 5040c8306c0..832c77d2cc7 100644 --- a/utils/src/main/java/com/cloud/utils/nio/Link.java +++ b/utils/src/main/java/com/cloud/utils/nio/Link.java @@ -48,6 +48,7 @@ import javax.net.ssl.TrustManagerFactory; import org.apache.cloudstack.framework.ca.CAService; import org.apache.cloudstack.utils.security.KeyStoreUtils; import org.apache.cloudstack.utils.security.SSLUtils; +import org.apache.commons.lang3.ObjectUtils; import org.apache.log4j.Logger; import com.cloud.utils.PropertiesUtil; @@ -591,6 +592,10 @@ public class Link { } public static boolean doHandshake(final SocketChannel socketChannel, final SSLEngine sslEngine) throws IOException { + return doHandshake(socketChannel, sslEngine, null); + } + + public static boolean doHandshake(final SocketChannel socketChannel, final SSLEngine sslEngine, Integer timeout) throws IOException { if (socketChannel == null || sslEngine == null) { return false; } @@ -605,12 +610,13 @@ public class Link { final long startTimeMills = System.currentTimeMillis(); HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus(); + long timeoutMillis = ObjectUtils.defaultIfNull(timeout, 30) * 1000L; while (handshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED && handshakeStatus != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { final long timeTaken = System.currentTimeMillis() - startTimeMills; - if (timeTaken > 30000L) { - s_logger.warn("SSL Handshake has taken more than 30s to connect to: " + socketChannel.getRemoteAddress() + - ". Please investigate this connection."); + if (timeTaken > timeoutMillis) { + s_logger.warn(String.format("SSL Handshake has taken more than 30s to connect to: %s" + + " while status: %s. Please investigate this connection.", socketChannel.getRemoteAddress(), handshakeStatus)); return false; } switch (handshakeStatus) { diff --git a/utils/src/main/java/com/cloud/utils/nio/NioClient.java b/utils/src/main/java/com/cloud/utils/nio/NioClient.java index 0eb58a59f62..603a6cb03e3 100644 --- a/utils/src/main/java/com/cloud/utils/nio/NioClient.java +++ b/utils/src/main/java/com/cloud/utils/nio/NioClient.java @@ -51,7 +51,7 @@ public class NioClient extends NioConnection { try { _clientConnection = SocketChannel.open(); - s_logger.info("Connecting to " + _host + ":" + _port); + s_logger.info(getConnectionName() + "Connecting to " + _host + ":" + _port); final InetSocketAddress peerAddr = new InetSocketAddress(_host, _port); _clientConnection.connect(peerAddr); _clientConnection.configureBlocking(false); @@ -61,13 +61,13 @@ public class NioClient extends NioConnection { sslEngine.setUseClientMode(true); sslEngine.setEnabledProtocols(SSLUtils.getSupportedProtocols(sslEngine.getEnabledProtocols())); sslEngine.beginHandshake(); - if (!Link.doHandshake(_clientConnection, sslEngine)) { - s_logger.error("SSL Handshake failed while connecting to host: " + _host + " port: " + _port); + if (!Link.doHandshake(_clientConnection, sslEngine, getSslHandshakeTimeout())) { + s_logger.error(getConnectionName() + "SSL Handshake failed while connecting to host: " + _host + " port: " + _port); _selector.close(); throw new IOException("SSL Handshake failed while connecting to host: " + _host + " port: " + _port); } - s_logger.info("SSL: Handshake done"); - s_logger.info("Connected to " + _host + ":" + _port); + s_logger.info(getConnectionName() + "SSL: Handshake done"); + s_logger.info(getConnectionName() + "Connected to " + _host + ":" + _port); final Link link = new Link(peerAddr, this); link.setSSLEngine(sslEngine); @@ -81,6 +81,7 @@ public class NioClient extends NioConnection { _selector.close(); throw new IOException("Failed to initialise security", e); } catch (final IOException e) { + s_logger.error(getConnectionName() + "IOException", e); _selector.close(); throw e; } diff --git a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java index 9a5bf7e4153..5e17fe05bf0 100644 --- a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java +++ b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java @@ -32,17 +32,21 @@ import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; +import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import javax.net.ssl.SSLEngine; @@ -73,6 +77,13 @@ public abstract class NioConnection implements Callable { protected ExecutorService _executor; protected ExecutorService _sslHandshakeExecutor; protected CAService caService; + protected Integer sslHandshakeTimeout = null; + private final AtomicInteger activeAcceptConnections = new AtomicInteger(0); + private BlockingQueue sslHandshakeQueue; + + public String getConnectionName() { + return String.format("%s:: ", _name); + } public NioConnection(final String name, final int port, final int workers, final HandlerFactory factory) { _name = name; @@ -80,8 +91,12 @@ public abstract class NioConnection implements Callable { _selector = null; _port = port; _factory = factory; - _executor = new ThreadPoolExecutor(workers, 5 * workers, 1, TimeUnit.DAYS, new LinkedBlockingQueue(), new NamedThreadFactory(name + "-Handler")); - _sslHandshakeExecutor = Executors.newCachedThreadPool(new NamedThreadFactory(name + "-SSLHandshakeHandler")); + _executor = new ThreadPoolExecutor(workers, 5 * workers, 1, TimeUnit.DAYS, + new LinkedBlockingQueue<>(), new NamedThreadFactory(name + "-Handler")); + sslHandshakeQueue = new LinkedBlockingQueue<>(5 * workers); + _sslHandshakeExecutor = new ThreadPoolExecutor(workers, 5 * workers, 90, + TimeUnit.SECONDS, sslHandshakeQueue, + new NamedThreadFactory(name + "-Handler"), new ThreadPoolExecutor.AbortPolicy()); } public void setCAService(final CAService caService) { @@ -94,13 +109,13 @@ public abstract class NioConnection implements Callable { try { init(); } catch (final ConnectException e) { - s_logger.warn("Unable to connect to remote: is there a server running on port " + _port); + s_logger.warn(getConnectionName() + "Unable to connect to remote: is there a server running on port" + _port); return; } catch (final IOException e) { - s_logger.error("Unable to initialize the threads.", e); + s_logger.error(getConnectionName() + "Unable to initialize the threads.", e); throw new NioConnectionException(e.getMessage(), e); } catch (final Exception e) { - s_logger.error("Unable to initialize the threads due to unknown exception.", e); + s_logger.error(getConnectionName() + "Unable to initialize the threads due to unknown exception.", e); throw new NioConnectionException(e.getMessage(), e); } _isStartup = true; @@ -190,6 +205,8 @@ public abstract class NioConnection implements Callable { abstract void unregisterLink(InetSocketAddress saddr); protected void accept(final SelectionKey key) throws IOException { + s_logger.info(String.format("%s------------------active accept connections: %d, queue: %d", + getConnectionName(), activeAcceptConnections.get(), sslHandshakeQueue.size())); final ServerSocketChannel serverSocketChannel = (ServerSocketChannel)key.channel(); final SocketChannel socketChannel = serverSocketChannel.accept(); socketChannel.configureBlocking(false); @@ -198,51 +215,49 @@ public abstract class NioConnection implements Callable { socket.setKeepAlive(true); if (s_logger.isTraceEnabled()) { - s_logger.trace("Connection accepted for " + socket); + s_logger.trace(getConnectionName() + "Connection accepted for " + socket); } - final SSLEngine sslEngine; try { - sslEngine = Link.initServerSSLEngine(caService, socketChannel.getRemoteAddress().toString()); - sslEngine.setUseClientMode(false); - sslEngine.setEnabledProtocols(SSLUtils.getSupportedProtocols(sslEngine.getEnabledProtocols())); final NioConnection nioConnection = this; - _sslHandshakeExecutor.submit(new Runnable() { - @Override - public void run() { - _selector.wakeup(); - try { - sslEngine.beginHandshake(); - if (!Link.doHandshake(socketChannel, sslEngine)) { - throw new IOException("SSL handshake timed out with " + socketChannel.getRemoteAddress()); - } - if (s_logger.isTraceEnabled()) { - s_logger.trace("SSL: Handshake done"); - } - final InetSocketAddress saddr = (InetSocketAddress)socket.getRemoteSocketAddress(); - final Link link = new Link(saddr, nioConnection); - link.setSSLEngine(sslEngine); - link.setKey(socketChannel.register(key.selector(), SelectionKey.OP_READ, link)); - final Task task = _factory.create(Task.Type.CONNECT, link, null); - registerLink(saddr, link); - _executor.submit(task); - } catch (IOException e) { - if (s_logger.isTraceEnabled()) { - s_logger.trace("Connection closed due to failure: " + e.getMessage()); - } - closeAutoCloseable(socket, "accepting socket"); - closeAutoCloseable(socketChannel, "accepting socketChannel"); - } finally { - _selector.wakeup(); + _sslHandshakeExecutor.submit(() -> { + activeAcceptConnections.incrementAndGet(); + _selector.wakeup(); + try { + final SSLEngine sslEngine = Link.initServerSSLEngine(caService, socketChannel.getRemoteAddress().toString()); + sslEngine.setUseClientMode(false); + sslEngine.setEnabledProtocols(SSLUtils.getSupportedProtocols(sslEngine.getEnabledProtocols())); + sslEngine.beginHandshake(); + if (!Link.doHandshake(socketChannel, sslEngine)) { + throw new IOException("SSL handshake timed out with " + socketChannel.getRemoteAddress()); } + if (s_logger.isTraceEnabled()) { + s_logger.trace("SSL: Handshake done"); + } + final InetSocketAddress saddr = (InetSocketAddress)socket.getRemoteSocketAddress(); + final Link link = new Link(saddr, nioConnection); + link.setSSLEngine(sslEngine); + link.setKey(socketChannel.register(key.selector(), SelectionKey.OP_READ, link)); + final Task task = _factory.create(Task.Type.CONNECT, link, null); + registerLink(saddr, link); + _executor.submit(task); + } catch (final GeneralSecurityException | IOException e) { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Connection closed due to failure: " + e.getMessage()); + } + closeAutoCloseable(socket, "accepting socket"); + closeAutoCloseable(socketChannel, "accepting socketChannel"); + } finally { + activeAcceptConnections.decrementAndGet(); + _selector.wakeup(); } }); - } catch (final Exception e) { + } catch (final RejectedExecutionException e) { if (s_logger.isTraceEnabled()) { - s_logger.trace("Connection closed due to failure: " + e.getMessage()); + s_logger.trace("Task rejected: " + e.getMessage()); } - closeAutoCloseable(socket, "accepting socket"); - closeAutoCloseable(socketChannel, "accepting socketChannel"); + closeAutoCloseable(socket, "Rejecting connection - accepting socket"); + closeAutoCloseable(socketChannel, "Rejecting connection - accepting socketChannel"); } finally { _selector.wakeup(); } @@ -259,7 +274,7 @@ public abstract class NioConnection implements Callable { try { _executor.submit(task); } catch (final Exception e) { - s_logger.warn("Exception occurred when submitting the task", e); + s_logger.warn(getConnectionName() + "Exception occurred when submitting the task", e); } } } @@ -283,7 +298,7 @@ public abstract class NioConnection implements Callable { try { _executor.submit(task); } catch (final Exception e) { - s_logger.warn("Exception occurred when submitting the task", e); + s_logger.warn(getConnectionName() + "Exception occurred when submitting the task", e); } } catch (final Exception e) { logDebug(e, key, 1); @@ -315,7 +330,7 @@ public abstract class NioConnection implements Callable { } } - s_logger.debug("Location " + loc + ": Socket " + socket + " closed on read. Probably -1 returned: " + e.getMessage()); + s_logger.debug(getConnectionName() + "Location " + loc + ": Socket " + socket + " closed on read. Probably -1 returned: " + e.getMessage()); } } @@ -412,7 +427,7 @@ public abstract class NioConnection implements Callable { try { _executor.submit(task); } catch (final Exception e) { - s_logger.warn("Exception occurred when submitting the task", e); + s_logger.warn(String.format("Exception occurred when submitting the task for connect: %s", socket), e); } } catch (final IOException e) { logTrace(e, key, 2); @@ -512,4 +527,12 @@ public abstract class NioConnection implements Callable { this.att = att; } } + + public Integer getSslHandshakeTimeout() { + return sslHandshakeTimeout; + } + + public void setSslHandshakeTimeout(Integer sslHandshakeTimeout) { + this.sslHandshakeTimeout = sslHandshakeTimeout; + } } diff --git a/utils/src/main/java/com/cloud/utils/nio/NioServer.java b/utils/src/main/java/com/cloud/utils/nio/NioServer.java index 0f83eda57b5..3fc3ec156bd 100644 --- a/utils/src/main/java/com/cloud/utils/nio/NioServer.java +++ b/utils/src/main/java/com/cloud/utils/nio/NioServer.java @@ -38,9 +38,10 @@ public class NioServer extends NioConnection { protected WeakHashMap _links; - public NioServer(final String name, final int port, final int workers, final HandlerFactory factory, final CAService caService) { + public NioServer(final String name, final int port, final int workers, final HandlerFactory factory, final CAService caService, final Integer sslHandShakeTimeout) { super(name, port, workers, factory); setCAService(caService); + setSslHandshakeTimeout(sslHandShakeTimeout); _localAddr = null; _links = new WeakHashMap(1024); } diff --git a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java index 0a9deea1a9d..692278d20ce 100644 --- a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java +++ b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java @@ -98,7 +98,7 @@ public class NioTest { testBytes = new byte[1000000]; randomGenerator.nextBytes(testBytes); - server = new NioServer("NioTestServer", 0, 1, new NioTestServer(), null); + server = new NioServer("NioTestServer", 0, 1, new NioTestServer(), null, null); try { server.start(); } catch (final NioConnectionException e) { From fa50740514a5100432f89a0fc65285aec6572b94 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 26 Sep 2024 12:10:38 +0530 Subject: [PATCH 34/62] wip Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/agent/AgentShell.java | 7 +- .../cloud/agent/manager/AgentManagerImpl.java | 13 +++- .../utils/backoff/impl/RangeTimeBackoff.java | 72 +++++++++++++++++++ .../java/com/cloud/utils/nio/NioClient.java | 2 +- .../com/cloud/utils/nio/NioConnection.java | 45 +++++++----- .../java/com/cloud/utils/nio/NioServer.java | 6 +- .../cloudstack/utils/security/SSLUtils.java | 4 +- .../com/cloud/utils/testcase/NioTest.java | 2 +- 8 files changed, 124 insertions(+), 27 deletions(-) create mode 100644 utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java diff --git a/agent/src/main/java/com/cloud/agent/AgentShell.java b/agent/src/main/java/com/cloud/agent/AgentShell.java index ef042496a37..49f8aecbcf5 100644 --- a/agent/src/main/java/com/cloud/agent/AgentShell.java +++ b/agent/src/main/java/com/cloud/agent/AgentShell.java @@ -403,9 +403,12 @@ public class AgentShell implements IAgentShell, Daemon { _properties.put(cmdLineProp.getKey(), cmdLineProp.getValue()); } - s_logger.info("Defaulting to the constant time backoff algorithm"); + s_logger.info("Defaulting to the range time backoff algorithm"); _backoff = new ConstantTimeBackoff(); - _backoff.configure("ConstantTimeBackoff", new HashMap()); + Map map = new HashMap<>(); + map.put("minSeconds", _properties.getProperty("backoff.min.seconds")); + map.put("maxSeconds", _properties.getProperty("backoff.max.seconds")); + _backoff.configure("RangeTimeBackoff", map); } private void launchAgent() throws ConfigurationException { diff --git a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java index 8d0e0b09780..57e6143ddb8 100644 --- a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java @@ -197,8 +197,15 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl protected final ConfigKey Workers = new ConfigKey("Advanced", Integer.class, "workers", "5", "Number of worker threads handling remote agent connections.", false); protected final ConfigKey Port = new ConfigKey("Advanced", Integer.class, "port", "8250", "Port to listen on for remote agent connections.", false); - protected final ConfigKey RemoteAgentSslHandshakeTimeout = new ConfigKey<>("Advanced", Integer.class, "agent.ssl.handshake.timeout", "30", + protected final ConfigKey RemoteAgentSslHandshakeTimeout = new ConfigKey<>("Advanced", + Integer.class, "agent.ssl.handshake.timeout", "30", "Seconds after which SSL handshake times out during remote agent connections.", false); + protected final ConfigKey RemoteAgentSslHandshakeMinWorkers = new ConfigKey<>("Advanced", + Integer.class, "agent.ssl.handshake.min.workers", "5", + "Number of minimum worker threads handling SSL handshake with remote agents.", false); + protected final ConfigKey RemoteAgentSslHandshakeMaxWorkers = new ConfigKey<>("Advanced", + Integer.class, "agent.ssl.handshake.min.workers", "100", + "Number of maximum worker threads handling SSL handshake with remote agents.", false); protected final ConfigKey AlertWait = new ConfigKey("Advanced", Integer.class, "alert.wait", "1800", "Seconds to wait before alerting on a disconnected agent", true); protected final ConfigKey DirectAgentLoadSize = new ConfigKey("Advanced", Integer.class, "direct.agent.load.size", "16", @@ -233,7 +240,9 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl // allow core threads to time out even when there are no items in the queue _connectExecutor.allowCoreThreadTimeOut(true); - _connection = new NioServer("AgentManager", Port.value(), Workers.value() + 10, this, caService, RemoteAgentSslHandshakeTimeout.value()); + _connection = new NioServer("AgentManager", Port.value(), Workers.value() + 10, + RemoteAgentSslHandshakeMinWorkers.value(), RemoteAgentSslHandshakeMaxWorkers.value(), this, + caService, RemoteAgentSslHandshakeTimeout.value()); s_logger.info("Listening on " + Port.value() + " with " + Workers.value() + " workers"); // executes all agent commands other than cron and ping diff --git a/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java b/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java new file mode 100644 index 00000000000..9b513285309 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java @@ -0,0 +1,72 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +package com.cloud.utils.backoff.impl; + +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ThreadLocalRandom; + +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.backoff.BackoffAlgorithm; +import com.cloud.utils.component.AdapterBase; +import org.apache.log4j.Logger; + +/** + * An implementation of BackoffAlgorithm that waits for some random seconds + * within a given range. + * After the time the client can try to perform the operation again. + * + **/ +public class RangeTimeBackoff extends AdapterBase implements BackoffAlgorithm { + private static final int DEFAULT_MIN_TIME = 5; + private int minTime = DEFAULT_MIN_TIME; + private int maxTime = 3 * DEFAULT_MIN_TIME; + private final Map asleep = new ConcurrentHashMap<>(); + private static final Logger LOG = Logger.getLogger(RangeTimeBackoff.class.getName()); + + @Override + public void waitBeforeRetry() { + Thread current = Thread.currentThread(); + try { + asleep.put(current.getName(), current); + long time = ThreadLocalRandom.current().nextInt(minTime, maxTime) * 1000L; + Thread.sleep(time); + } catch (InterruptedException e) { + // JMX or other threads may interrupt this thread, but let's log it + // anyway, no exception to log as this is not an error + LOG.info("Thread " + current.getName() + " interrupted while waiting for retry"); + } finally { + asleep.remove(current.getName()); + } + return; + } + + @Override + public void reset() { + } + + @Override + public boolean configure(String name, Map params) { + minTime = NumbersUtil.parseInt((String)params.get("minSeconds"), DEFAULT_MIN_TIME); + maxTime = NumbersUtil.parseInt((String)params.get("maxSeconds"), minTime * 3); + return true; + } +} diff --git a/utils/src/main/java/com/cloud/utils/nio/NioClient.java b/utils/src/main/java/com/cloud/utils/nio/NioClient.java index 603a6cb03e3..51448c88875 100644 --- a/utils/src/main/java/com/cloud/utils/nio/NioClient.java +++ b/utils/src/main/java/com/cloud/utils/nio/NioClient.java @@ -39,7 +39,7 @@ public class NioClient extends NioConnection { protected SocketChannel _clientConnection; public NioClient(final String name, final String host, final int port, final int workers, final HandlerFactory factory) { - super(name, port, workers, factory); + super(name, port, workers, 1, 2, factory); _host = host; } diff --git a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java index 5e17fe05bf0..ce2346d2a34 100644 --- a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java +++ b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java @@ -79,24 +79,27 @@ public abstract class NioConnection implements Callable { protected CAService caService; protected Integer sslHandshakeTimeout = null; private final AtomicInteger activeAcceptConnections = new AtomicInteger(0); - private BlockingQueue sslHandshakeQueue; + private final BlockingQueue workerQueue; + private final BlockingQueue sslHandshakeQueue; public String getConnectionName() { return String.format("%s:: ", _name); } - public NioConnection(final String name, final int port, final int workers, final HandlerFactory factory) { + public NioConnection(final String name, final int port, final int workers, final int sslHandshakeMinWorkers, + final int sslHandshakeMaxWorkers, final HandlerFactory factory) { _name = name; _isRunning = false; _selector = null; _port = port; _factory = factory; + workerQueue = new LinkedBlockingQueue<>(5 * workers); _executor = new ThreadPoolExecutor(workers, 5 * workers, 1, TimeUnit.DAYS, - new LinkedBlockingQueue<>(), new NamedThreadFactory(name + "-Handler")); - sslHandshakeQueue = new LinkedBlockingQueue<>(5 * workers); - _sslHandshakeExecutor = new ThreadPoolExecutor(workers, 5 * workers, 90, - TimeUnit.SECONDS, sslHandshakeQueue, - new NamedThreadFactory(name + "-Handler"), new ThreadPoolExecutor.AbortPolicy()); + workerQueue, new NamedThreadFactory(name + "-Handler"), new ThreadPoolExecutor.AbortPolicy()); + sslHandshakeQueue = new LinkedBlockingQueue<>(sslHandshakeMaxWorkers); + _sslHandshakeExecutor = new ThreadPoolExecutor(sslHandshakeMinWorkers, sslHandshakeMaxWorkers, 30, + TimeUnit.MINUTES, sslHandshakeQueue, new NamedThreadFactory(name + "-Handler"), + new ThreadPoolExecutor.AbortPolicy()); } public void setCAService(final CAService caService) { @@ -205,8 +208,8 @@ public abstract class NioConnection implements Callable { abstract void unregisterLink(InetSocketAddress saddr); protected void accept(final SelectionKey key) throws IOException { - s_logger.info(String.format("%s------------------active accept connections: %d, queue: %d", - getConnectionName(), activeAcceptConnections.get(), sslHandshakeQueue.size())); + s_logger.info(String.format("%s------------------active accept c0nnections: %d, queue: %d, worker-queue: %d", + getConnectionName(), activeAcceptConnections.get(), sslHandshakeQueue.size(), workerQueue.size())); final ServerSocketChannel serverSocketChannel = (ServerSocketChannel)key.channel(); final SocketChannel socketChannel = serverSocketChannel.accept(); socketChannel.configureBlocking(false); @@ -221,20 +224,24 @@ public abstract class NioConnection implements Callable { try { final NioConnection nioConnection = this; _sslHandshakeExecutor.submit(() -> { - activeAcceptConnections.incrementAndGet(); + final InetSocketAddress saddr = (InetSocketAddress)socket.getRemoteSocketAddress(); + int connections = activeAcceptConnections.incrementAndGet(); + Long startTime = System.currentTimeMillis(); + s_logger.info(String.format("%s-start-----------------active accept c0nnections: %d, " + + "accept-queue: %d, worker-queue: %d", + saddr, connections, sslHandshakeQueue.size(), workerQueue.size())); _selector.wakeup(); try { final SSLEngine sslEngine = Link.initServerSSLEngine(caService, socketChannel.getRemoteAddress().toString()); sslEngine.setUseClientMode(false); sslEngine.setEnabledProtocols(SSLUtils.getSupportedProtocols(sslEngine.getEnabledProtocols())); sslEngine.beginHandshake(); - if (!Link.doHandshake(socketChannel, sslEngine)) { - throw new IOException("SSL handshake timed out with " + socketChannel.getRemoteAddress()); + if (!Link.doHandshake(socketChannel, sslEngine, getSslHandshakeTimeout())) { + throw new IOException("SSL handshake timed out with " + saddr); } if (s_logger.isTraceEnabled()) { s_logger.trace("SSL: Handshake done"); } - final InetSocketAddress saddr = (InetSocketAddress)socket.getRemoteSocketAddress(); final Link link = new Link(saddr, nioConnection); link.setSSLEngine(sslEngine); link.setKey(socketChannel.register(key.selector(), SelectionKey.OP_READ, link)); @@ -243,18 +250,22 @@ public abstract class NioConnection implements Callable { _executor.submit(task); } catch (final GeneralSecurityException | IOException e) { if (s_logger.isTraceEnabled()) { - s_logger.trace("Connection closed due to failure: " + e.getMessage()); + s_logger.trace(socket.getRemoteSocketAddress()+ "Connection closed due to failure: " + e.getMessage()); } closeAutoCloseable(socket, "accepting socket"); closeAutoCloseable(socketChannel, "accepting socketChannel"); } finally { - activeAcceptConnections.decrementAndGet(); + connections = activeAcceptConnections.decrementAndGet(); + s_logger.info(String.format("%s-end----active accept c0nnections: %d, accept-queue: %d," + + "worker-queue: %d, time taken: %d", + saddr, connections, sslHandshakeQueue.size(), workerQueue.size(), + (System.currentTimeMillis() - startTime))); _selector.wakeup(); } }); } catch (final RejectedExecutionException e) { - if (s_logger.isTraceEnabled()) { - s_logger.trace("Task rejected: " + e.getMessage()); + if (s_logger.isInfoEnabled()) { + s_logger.trace(socket.getRemoteSocketAddress()+ " Accept Task rejected: " + e.getMessage()); } closeAutoCloseable(socket, "Rejecting connection - accepting socket"); closeAutoCloseable(socketChannel, "Rejecting connection - accepting socketChannel"); diff --git a/utils/src/main/java/com/cloud/utils/nio/NioServer.java b/utils/src/main/java/com/cloud/utils/nio/NioServer.java index 3fc3ec156bd..59f90a4a8ef 100644 --- a/utils/src/main/java/com/cloud/utils/nio/NioServer.java +++ b/utils/src/main/java/com/cloud/utils/nio/NioServer.java @@ -38,8 +38,10 @@ public class NioServer extends NioConnection { protected WeakHashMap _links; - public NioServer(final String name, final int port, final int workers, final HandlerFactory factory, final CAService caService, final Integer sslHandShakeTimeout) { - super(name, port, workers, factory); + public NioServer(final String name, final int port, final int workers, final int sslHandshakeMinWorkers, + final int sslHandshakeMaxWorkers, final HandlerFactory factory, final CAService caService, + final Integer sslHandShakeTimeout) { + super(name, port, workers, sslHandshakeMinWorkers, sslHandshakeMaxWorkers, factory); setCAService(caService); setSslHandshakeTimeout(sslHandShakeTimeout); _localAddr = null; diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java b/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java index 8016f5a1916..36df09453bb 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java @@ -46,7 +46,7 @@ public class SSLUtils { * It returns recommended protocols that are considered secure. */ public static String[] getRecommendedProtocols() { - return new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" }; + return new String[] { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" }; } /** @@ -66,7 +66,7 @@ public class SSLUtils { } public static SSLContext getSSLContext() throws NoSuchAlgorithmException { - return SSLContext.getInstance("TLSv1.2"); + return SSLContext.getInstance("TLSv1.3"); } public static SSLContext getSSLContext(String provider) throws NoSuchAlgorithmException, NoSuchProviderException { diff --git a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java index 692278d20ce..bc5b3aed227 100644 --- a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java +++ b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java @@ -98,7 +98,7 @@ public class NioTest { testBytes = new byte[1000000]; randomGenerator.nextBytes(testBytes); - server = new NioServer("NioTestServer", 0, 1, new NioTestServer(), null, null); + server = new NioServer("NioTestServer", 0, 1, 1, 1, new NioTestServer(), null, null); try { server.start(); } catch (final NioConnectionException e) { From adae7c88b8da30cd777cda462bdc26eaedc4dbf6 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 27 Sep 2024 13:00:38 +0530 Subject: [PATCH 35/62] changes Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/agent/AgentShell.java | 48 ++++++++++--------- .../cloud/agent/manager/AgentManagerImpl.java | 4 +- .../utils/backoff/impl/RangeTimeBackoff.java | 5 +- .../java/com/cloud/utils/nio/NioClient.java | 10 ++-- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/agent/src/main/java/com/cloud/agent/AgentShell.java b/agent/src/main/java/com/cloud/agent/AgentShell.java index 49f8aecbcf5..faa2322d8b6 100644 --- a/agent/src/main/java/com/cloud/agent/AgentShell.java +++ b/agent/src/main/java/com/cloud/agent/AgentShell.java @@ -16,28 +16,6 @@ // under the License. package com.cloud.agent; -import com.cloud.agent.Agent.ExitStatus; -import com.cloud.agent.dao.StorageComponent; -import com.cloud.agent.dao.impl.PropertiesStorage; -import com.cloud.agent.properties.AgentProperties; -import com.cloud.agent.properties.AgentPropertiesFileHandler; -import com.cloud.resource.ServerResource; -import com.cloud.utils.LogUtils; -import com.cloud.utils.ProcessUtil; -import com.cloud.utils.PropertiesUtil; -import com.cloud.utils.backoff.BackoffAlgorithm; -import com.cloud.utils.backoff.impl.ConstantTimeBackoff; -import com.cloud.utils.exception.CloudRuntimeException; -import org.apache.commons.daemon.Daemon; -import org.apache.commons.daemon.DaemonContext; -import org.apache.commons.daemon.DaemonInitException; -import org.apache.commons.lang.math.NumberUtils; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; -import org.apache.log4j.xml.DOMConfigurator; - -import javax.naming.ConfigurationException; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -52,6 +30,30 @@ import java.util.Map; import java.util.Properties; import java.util.UUID; +import javax.naming.ConfigurationException; + +import org.apache.commons.daemon.Daemon; +import org.apache.commons.daemon.DaemonContext; +import org.apache.commons.daemon.DaemonInitException; +import org.apache.commons.lang.math.NumberUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; +import org.apache.log4j.xml.DOMConfigurator; + +import com.cloud.agent.Agent.ExitStatus; +import com.cloud.agent.dao.StorageComponent; +import com.cloud.agent.dao.impl.PropertiesStorage; +import com.cloud.agent.properties.AgentProperties; +import com.cloud.agent.properties.AgentPropertiesFileHandler; +import com.cloud.resource.ServerResource; +import com.cloud.utils.LogUtils; +import com.cloud.utils.ProcessUtil; +import com.cloud.utils.PropertiesUtil; +import com.cloud.utils.backoff.BackoffAlgorithm; +import com.cloud.utils.backoff.impl.RangeTimeBackoff; +import com.cloud.utils.exception.CloudRuntimeException; + public class AgentShell implements IAgentShell, Daemon { private static final Logger s_logger = Logger.getLogger(AgentShell.class.getName()); @@ -404,7 +406,7 @@ public class AgentShell implements IAgentShell, Daemon { } s_logger.info("Defaulting to the range time backoff algorithm"); - _backoff = new ConstantTimeBackoff(); + _backoff = new RangeTimeBackoff(); Map map = new HashMap<>(); map.put("minSeconds", _properties.getProperty("backoff.min.seconds")); map.put("maxSeconds", _properties.getProperty("backoff.max.seconds")); diff --git a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java index 57e6143ddb8..eb77f2944a5 100644 --- a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java @@ -204,7 +204,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl Integer.class, "agent.ssl.handshake.min.workers", "5", "Number of minimum worker threads handling SSL handshake with remote agents.", false); protected final ConfigKey RemoteAgentSslHandshakeMaxWorkers = new ConfigKey<>("Advanced", - Integer.class, "agent.ssl.handshake.min.workers", "100", + Integer.class, "agent.ssl.handshake.max.workers", "50", "Number of maximum worker threads handling SSL handshake with remote agents.", false); protected final ConfigKey AlertWait = new ConfigKey("Advanced", Integer.class, "alert.wait", "1800", "Seconds to wait before alerting on a disconnected agent", true); @@ -1850,7 +1850,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl public ConfigKey[] getConfigKeys() { return new ConfigKey[] { CheckTxnBeforeSending, Workers, Port, Wait, AlertWait, DirectAgentLoadSize, DirectAgentPoolSize, DirectAgentThreadCap, EnableKVMAutoEnableDisable, ReadyCommandWait, - RemoteAgentSslHandshakeTimeout + RemoteAgentSslHandshakeTimeout, RemoteAgentSslHandshakeMinWorkers, RemoteAgentSslHandshakeMaxWorkers }; } diff --git a/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java b/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java index 9b513285309..8104caa69c6 100644 --- a/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java +++ b/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java @@ -19,15 +19,15 @@ package com.cloud.utils.backoff.impl; -import java.util.Collection; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; +import org.apache.log4j.Logger; + import com.cloud.utils.NumbersUtil; import com.cloud.utils.backoff.BackoffAlgorithm; import com.cloud.utils.component.AdapterBase; -import org.apache.log4j.Logger; /** * An implementation of BackoffAlgorithm that waits for some random seconds @@ -48,6 +48,7 @@ public class RangeTimeBackoff extends AdapterBase implements BackoffAlgorithm { try { asleep.put(current.getName(), current); long time = ThreadLocalRandom.current().nextInt(minTime, maxTime) * 1000L; + LOG.info("Waiting " + current.getName() + " for " + time); Thread.sleep(time); } catch (InterruptedException e) { // JMX or other threads may interrupt this thread, but let's log it diff --git a/utils/src/main/java/com/cloud/utils/nio/NioClient.java b/utils/src/main/java/com/cloud/utils/nio/NioClient.java index 51448c88875..a2e76e1d224 100644 --- a/utils/src/main/java/com/cloud/utils/nio/NioClient.java +++ b/utils/src/main/java/com/cloud/utils/nio/NioClient.java @@ -51,7 +51,7 @@ public class NioClient extends NioConnection { try { _clientConnection = SocketChannel.open(); - s_logger.info(getConnectionName() + "Connecting to " + _host + ":" + _port); + s_logger.info("Connecting to " + _host + ":" + _port); final InetSocketAddress peerAddr = new InetSocketAddress(_host, _port); _clientConnection.connect(peerAddr); _clientConnection.configureBlocking(false); @@ -62,12 +62,12 @@ public class NioClient extends NioConnection { sslEngine.setEnabledProtocols(SSLUtils.getSupportedProtocols(sslEngine.getEnabledProtocols())); sslEngine.beginHandshake(); if (!Link.doHandshake(_clientConnection, sslEngine, getSslHandshakeTimeout())) { - s_logger.error(getConnectionName() + "SSL Handshake failed while connecting to host: " + _host + " port: " + _port); + s_logger.error("SSL Handshake failed while connecting to host: " + _host + " port: " + _port); _selector.close(); throw new IOException("SSL Handshake failed while connecting to host: " + _host + " port: " + _port); } - s_logger.info(getConnectionName() + "SSL: Handshake done"); - s_logger.info(getConnectionName() + "Connected to " + _host + ":" + _port); + s_logger.info("SSL: Handshake done"); + s_logger.info("Connected to " + _host + ":" + _port); final Link link = new Link(peerAddr, this); link.setSSLEngine(sslEngine); @@ -81,7 +81,7 @@ public class NioClient extends NioConnection { _selector.close(); throw new IOException("Failed to initialise security", e); } catch (final IOException e) { - s_logger.error(getConnectionName() + "IOException", e); + s_logger.error("IOException", e); _selector.close(); throw e; } From d9269842d0eba0c881bfb029620f1920ab59576f Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 30 Sep 2024 17:40:42 +0530 Subject: [PATCH 36/62] changes - add timeout for CheckNetworkCommand - use SychnonousQueue for ssl/tls handshake worker - revert to TLSv1.2 Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/agent/api/CheckNetworkCommand.java | 1 + utils/src/main/java/com/cloud/utils/nio/NioConnection.java | 3 ++- .../java/org/apache/cloudstack/utils/security/SSLUtils.java | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/com/cloud/agent/api/CheckNetworkCommand.java b/core/src/main/java/com/cloud/agent/api/CheckNetworkCommand.java index 717af2afa06..cb541690425 100644 --- a/core/src/main/java/com/cloud/agent/api/CheckNetworkCommand.java +++ b/core/src/main/java/com/cloud/agent/api/CheckNetworkCommand.java @@ -29,6 +29,7 @@ public class CheckNetworkCommand extends Command { public CheckNetworkCommand(List networkInfoList) { this.networkInfoList = networkInfoList; + setWait(120); } public List getPhysicalNetworkInfoList() { diff --git a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java index ce2346d2a34..8e2481a3fd0 100644 --- a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java +++ b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java @@ -44,6 +44,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -96,7 +97,7 @@ public abstract class NioConnection implements Callable { workerQueue = new LinkedBlockingQueue<>(5 * workers); _executor = new ThreadPoolExecutor(workers, 5 * workers, 1, TimeUnit.DAYS, workerQueue, new NamedThreadFactory(name + "-Handler"), new ThreadPoolExecutor.AbortPolicy()); - sslHandshakeQueue = new LinkedBlockingQueue<>(sslHandshakeMaxWorkers); + sslHandshakeQueue = new SynchronousQueue<>(); _sslHandshakeExecutor = new ThreadPoolExecutor(sslHandshakeMinWorkers, sslHandshakeMaxWorkers, 30, TimeUnit.MINUTES, sslHandshakeQueue, new NamedThreadFactory(name + "-Handler"), new ThreadPoolExecutor.AbortPolicy()); diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java b/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java index 36df09453bb..8016f5a1916 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/security/SSLUtils.java @@ -46,7 +46,7 @@ public class SSLUtils { * It returns recommended protocols that are considered secure. */ public static String[] getRecommendedProtocols() { - return new String[] { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" }; + return new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" }; } /** @@ -66,7 +66,7 @@ public class SSLUtils { } public static SSLContext getSSLContext() throws NoSuchAlgorithmException { - return SSLContext.getInstance("TLSv1.3"); + return SSLContext.getInstance("TLSv1.2"); } public static SSLContext getSSLContext(String provider) throws NoSuchAlgorithmException, NoSuchProviderException { From f7f9249be5b3284023fb907817ed09fec45e73c1 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 30 Sep 2024 18:09:34 +0530 Subject: [PATCH 37/62] fix Signed-off-by: Abhishek Kumar --- utils/src/main/java/com/cloud/utils/nio/NioConnection.java | 2 +- utils/src/test/java/com/cloud/utils/testcase/NioTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java index 8e2481a3fd0..5c1e10f99c6 100644 --- a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java +++ b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java @@ -97,7 +97,7 @@ public abstract class NioConnection implements Callable { workerQueue = new LinkedBlockingQueue<>(5 * workers); _executor = new ThreadPoolExecutor(workers, 5 * workers, 1, TimeUnit.DAYS, workerQueue, new NamedThreadFactory(name + "-Handler"), new ThreadPoolExecutor.AbortPolicy()); - sslHandshakeQueue = new SynchronousQueue<>(); + sslHandshakeQueue = new LinkedBlockingQueue<>(2 * sslHandshakeMaxWorkers); _sslHandshakeExecutor = new ThreadPoolExecutor(sslHandshakeMinWorkers, sslHandshakeMaxWorkers, 30, TimeUnit.MINUTES, sslHandshakeQueue, new NamedThreadFactory(name + "-Handler"), new ThreadPoolExecutor.AbortPolicy()); diff --git a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java index bc5b3aed227..4116f00deba 100644 --- a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java +++ b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java @@ -98,7 +98,7 @@ public class NioTest { testBytes = new byte[1000000]; randomGenerator.nextBytes(testBytes); - server = new NioServer("NioTestServer", 0, 1, 1, 1, new NioTestServer(), null, null); + server = new NioServer("NioTestServer", 0, 10, 1, 1, new NioTestServer(), null, null); try { server.start(); } catch (final NioConnectionException e) { From 9afb25a9699f5a278421a1e5b2f7c8cc1c1f669e Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 3 Oct 2024 15:54:21 +0530 Subject: [PATCH 38/62] fix Signed-off-by: Abhishek Kumar --- .../com/cloud/utils/nio/NioConnection.java | 61 ++++++++++--------- .../com/cloud/utils/testcase/NioTest.java | 2 +- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java index 5c1e10f99c6..49d33bcf300 100644 --- a/utils/src/main/java/com/cloud/utils/nio/NioConnection.java +++ b/utils/src/main/java/com/cloud/utils/nio/NioConnection.java @@ -79,14 +79,11 @@ public abstract class NioConnection implements Callable { protected ExecutorService _sslHandshakeExecutor; protected CAService caService; protected Integer sslHandshakeTimeout = null; + private int sslHandshakeMaxWorkers; private final AtomicInteger activeAcceptConnections = new AtomicInteger(0); private final BlockingQueue workerQueue; private final BlockingQueue sslHandshakeQueue; - public String getConnectionName() { - return String.format("%s:: ", _name); - } - public NioConnection(final String name, final int port, final int workers, final int sslHandshakeMinWorkers, final int sslHandshakeMaxWorkers, final HandlerFactory factory) { _name = name; @@ -94,10 +91,11 @@ public abstract class NioConnection implements Callable { _selector = null; _port = port; _factory = factory; + this.sslHandshakeMaxWorkers = sslHandshakeMaxWorkers; workerQueue = new LinkedBlockingQueue<>(5 * workers); _executor = new ThreadPoolExecutor(workers, 5 * workers, 1, TimeUnit.DAYS, workerQueue, new NamedThreadFactory(name + "-Handler"), new ThreadPoolExecutor.AbortPolicy()); - sslHandshakeQueue = new LinkedBlockingQueue<>(2 * sslHandshakeMaxWorkers); + sslHandshakeQueue = new SynchronousQueue<>(); _sslHandshakeExecutor = new ThreadPoolExecutor(sslHandshakeMinWorkers, sslHandshakeMaxWorkers, 30, TimeUnit.MINUTES, sslHandshakeQueue, new NamedThreadFactory(name + "-Handler"), new ThreadPoolExecutor.AbortPolicy()); @@ -113,13 +111,13 @@ public abstract class NioConnection implements Callable { try { init(); } catch (final ConnectException e) { - s_logger.warn(getConnectionName() + "Unable to connect to remote: is there a server running on port" + _port); + s_logger.warn("Unable to connect to remote: is there a server running on port" + _port); return; } catch (final IOException e) { - s_logger.error(getConnectionName() + "Unable to initialize the threads.", e); + s_logger.error("Unable to initialize the threads.", e); throw new NioConnectionException(e.getMessage(), e); } catch (final Exception e) { - s_logger.error(getConnectionName() + "Unable to initialize the threads due to unknown exception.", e); + s_logger.error("Unable to initialize the threads due to unknown exception.", e); throw new NioConnectionException(e.getMessage(), e); } _isStartup = true; @@ -209,28 +207,32 @@ public abstract class NioConnection implements Callable { abstract void unregisterLink(InetSocketAddress saddr); protected void accept(final SelectionKey key) throws IOException { - s_logger.info(String.format("%s------------------active accept c0nnections: %d, queue: %d, worker-queue: %d", - getConnectionName(), activeAcceptConnections.get(), sslHandshakeQueue.size(), workerQueue.size())); final ServerSocketChannel serverSocketChannel = (ServerSocketChannel)key.channel(); final SocketChannel socketChannel = serverSocketChannel.accept(); + if (activeAcceptConnections.get() >= sslHandshakeMaxWorkers) { + // Reject new connection if the server is busy + s_logger.warn("Server is busy. Rejecting new connection."); + if (socketChannel != null) { + socketChannel.close(); + } + _selector.wakeup(); + return; + } socketChannel.configureBlocking(false); final Socket socket = socketChannel.socket(); socket.setKeepAlive(true); if (s_logger.isTraceEnabled()) { - s_logger.trace(getConnectionName() + "Connection accepted for " + socket); + s_logger.trace("Connection accepted for " + socket); } try { final NioConnection nioConnection = this; _sslHandshakeExecutor.submit(() -> { - final InetSocketAddress saddr = (InetSocketAddress)socket.getRemoteSocketAddress(); - int connections = activeAcceptConnections.incrementAndGet(); - Long startTime = System.currentTimeMillis(); - s_logger.info(String.format("%s-start-----------------active accept c0nnections: %d, " + - "accept-queue: %d, worker-queue: %d", - saddr, connections, sslHandshakeQueue.size(), workerQueue.size())); + final InetSocketAddress socketAddress = (InetSocketAddress)socket.getRemoteSocketAddress(); + activeAcceptConnections.incrementAndGet(); + long startTime = System.currentTimeMillis(); _selector.wakeup(); try { final SSLEngine sslEngine = Link.initServerSSLEngine(caService, socketChannel.getRemoteAddress().toString()); @@ -238,16 +240,16 @@ public abstract class NioConnection implements Callable { sslEngine.setEnabledProtocols(SSLUtils.getSupportedProtocols(sslEngine.getEnabledProtocols())); sslEngine.beginHandshake(); if (!Link.doHandshake(socketChannel, sslEngine, getSslHandshakeTimeout())) { - throw new IOException("SSL handshake timed out with " + saddr); + throw new IOException("SSL handshake timed out with " + socketAddress); } if (s_logger.isTraceEnabled()) { s_logger.trace("SSL: Handshake done"); } - final Link link = new Link(saddr, nioConnection); + final Link link = new Link(socketAddress, nioConnection); link.setSSLEngine(sslEngine); link.setKey(socketChannel.register(key.selector(), SelectionKey.OP_READ, link)); final Task task = _factory.create(Task.Type.CONNECT, link, null); - registerLink(saddr, link); + registerLink(socketAddress, link); _executor.submit(task); } catch (final GeneralSecurityException | IOException e) { if (s_logger.isTraceEnabled()) { @@ -256,16 +258,17 @@ public abstract class NioConnection implements Callable { closeAutoCloseable(socket, "accepting socket"); closeAutoCloseable(socketChannel, "accepting socketChannel"); } finally { - connections = activeAcceptConnections.decrementAndGet(); - s_logger.info(String.format("%s-end----active accept c0nnections: %d, accept-queue: %d," + - "worker-queue: %d, time taken: %d", - saddr, connections, sslHandshakeQueue.size(), workerQueue.size(), - (System.currentTimeMillis() - startTime))); + int connections = activeAcceptConnections.decrementAndGet(); + if (s_logger.isTraceEnabled()) { + s_logger.trace(String.format("Accept task complete for %s - time taken: %d, " + + "active accept connections: %d", + socketAddress, (System.currentTimeMillis() - startTime), connections)); + } _selector.wakeup(); } }); } catch (final RejectedExecutionException e) { - if (s_logger.isInfoEnabled()) { + if (s_logger.isTraceEnabled()) { s_logger.trace(socket.getRemoteSocketAddress()+ " Accept Task rejected: " + e.getMessage()); } closeAutoCloseable(socket, "Rejecting connection - accepting socket"); @@ -286,7 +289,7 @@ public abstract class NioConnection implements Callable { try { _executor.submit(task); } catch (final Exception e) { - s_logger.warn(getConnectionName() + "Exception occurred when submitting the task", e); + s_logger.warn("Exception occurred when submitting the task", e); } } } @@ -310,7 +313,7 @@ public abstract class NioConnection implements Callable { try { _executor.submit(task); } catch (final Exception e) { - s_logger.warn(getConnectionName() + "Exception occurred when submitting the task", e); + s_logger.warn("Exception occurred when submitting the task", e); } } catch (final Exception e) { logDebug(e, key, 1); @@ -342,7 +345,7 @@ public abstract class NioConnection implements Callable { } } - s_logger.debug(getConnectionName() + "Location " + loc + ": Socket " + socket + " closed on read. Probably -1 returned: " + e.getMessage()); + s_logger.debug("Location " + loc + ": Socket " + socket + " closed on read. Probably -1 returned: " + e.getMessage()); } } diff --git a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java index 4116f00deba..d8d6adde747 100644 --- a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java +++ b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java @@ -98,7 +98,7 @@ public class NioTest { testBytes = new byte[1000000]; randomGenerator.nextBytes(testBytes); - server = new NioServer("NioTestServer", 0, 10, 1, 1, new NioTestServer(), null, null); + server = new NioServer("NioTestServer", 0, 10, 1, 2 * totalTestCount, new NioTestServer(), null, null); try { server.start(); } catch (final NioConnectionException e) { From a74403bd971730fe0ea5689bac82abe82e77764b Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 4 Oct 2024 16:49:39 +0530 Subject: [PATCH 39/62] revert logging changes Signed-off-by: Abhishek Kumar --- agent/src/main/java/com/cloud/agent/Agent.java | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/agent/src/main/java/com/cloud/agent/Agent.java b/agent/src/main/java/com/cloud/agent/Agent.java index eb584aaf2d9..9e0ee746c03 100644 --- a/agent/src/main/java/com/cloud/agent/Agent.java +++ b/agent/src/main/java/com/cloud/agent/Agent.java @@ -154,14 +154,6 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater private String _keystoreSetupPath; private String _keystoreCertImportPath; - protected String getConnectionName() { - return "Agent-" + _resource.getName(); - } - - protected String getConnectionNameLog() { - return String.format("%s:: ", getConnectionName()); - } - // for simulator use only public Agent(final IAgentShell shell) { _shell = shell; @@ -203,7 +195,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater } final String host = _shell.getNextHost(); - _connection = new NioClient(getConnectionName(), host, _shell.getPort(), _shell.getWorkers(), this); + _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this); // ((NioClient)_connection).setBindAddress(_shell.getPrivateIp()); @@ -544,7 +536,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater _resource.disconnected(); - s_logger.info(getConnectionNameLog() + "Lost connection to host: " + _shell.getConnectedHost() + ". Attempting reconnection while we still have " + _inProgress.get() + " commands in progress."); + s_logger.info("Lost connection to host: " + _shell.getConnectedHost() + ". Attempting reconnection while we still have " + _inProgress.get() + " commands in progress."); _connection.stop(); @@ -561,7 +553,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater do { final String host = _shell.getNextHost(); _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this); - s_logger.info(getConnectionNameLog() + "Reconnecting to host:" + host); + s_logger.info("Reconnecting to host:" + host); try { _connection.start(); } catch (final NioConnectionException e) { From b4fb97c886ab8f204129d42abb7703c4d30b5dae Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 4 Oct 2024 16:50:09 +0530 Subject: [PATCH 40/62] change in account role caching Signed-off-by: Abhishek Kumar --- .../acl/DynamicRoleBasedAPIAccessChecker.java | 36 +++++++------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java b/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java index 5933a965c2c..561d1102611 100644 --- a/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java +++ b/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java @@ -51,7 +51,7 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API private List services; private Map> annotationRoleBasedApisMap = new HashMap>(); - final private LazyCache>> accountRolePermissionsCache; + final private LazyCache accountCache; final private LazyCache>> rolePermissionsCache; private static final Logger LOGGER = Logger.getLogger(DynamicRoleBasedAPIAccessChecker.class.getName()); @@ -61,8 +61,8 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API for (RoleType roleType : RoleType.values()) { annotationRoleBasedApisMap.put(roleType, new HashSet()); } - accountRolePermissionsCache = new LazyCache<>(32, 60, - this::getAccountRolePermissions); + accountCache = new LazyCache<>(32, 60, + this::getAccountFromId); rolePermissionsCache = new LazyCache<>(32, 60, this::getRolePermissions); } @@ -110,22 +110,9 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API annotationRoleBasedApisMap.get(role.getRoleType()).contains(apiName); } - protected Pair> getAccountRolePermissions(long accountId) { - LOGGER.debug("RolePermissions not available in cache for-----------------------------" + accountId); - Account account = accountService.getAccount(accountId); - if (account == null) { - return null; - } - final Role accountRole = roleService.findRole(account.getRoleId()); - if (accountRole == null || accountRole.getId() < 1L) { - return new Pair<>(null, null); - } - - if (accountRole.getRoleType() == RoleType.Admin && accountRole.getId() == RoleType.Admin.getId()) { - return new Pair<>(accountRole, null); - } - - return new Pair<>(accountRole, roleService.findAllPermissionsBy(accountRole.getId())); + protected Account getAccountFromId(long accountId) { + LOGGER.debug("Account not available in cache for-----------------------------" + accountId); + return accountService.getAccount(accountId); } protected Pair> getRolePermissions(long roleId) { @@ -147,19 +134,20 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API if (!isEnabled()) { return true; } - Pair> accountRoleAndPermissions = accountRolePermissionsCache.get(user.getAccountId()); - if (accountRoleAndPermissions == null) { + Account account = accountCache.get(user.getAccountId()); + if (account == null) { throw new PermissionDeniedException(String.format("Account for user id [%s] cannot be found", user.getUuid())); } - final Role accountRole = accountRoleAndPermissions.first(); - if (accountRoleAndPermissions.first() == null) { + Pair> roleAndPermissions = rolePermissionsCache.get(account.getRoleId()); + final Role accountRole = roleAndPermissions.first(); + if (accountRole == null) { throw new PermissionDeniedException(String.format("Account role for user id [%s] cannot be found.", user.getUuid())); } if (accountRole.getRoleType() == RoleType.Admin && accountRole.getId() == RoleType.Admin.getId()) { LOGGER.info(String.format("Account for user id [%s] is Root Admin or Domain Admin, all APIs are allowed.", user.getUuid())); return true; } - List allPermissions = accountRoleAndPermissions.second(); + List allPermissions = roleAndPermissions.second(); if (checkApiPermissionByRole(accountRole, commandName, allPermissions)) { return true; } From d2075415ac60062c3917b5ab4f63ccefe62a9538 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 7 Oct 2024 15:32:06 +0530 Subject: [PATCH 41/62] remove logs from DynamicRoleBasedAPIAccessChecker Signed-off-by: Abhishek Kumar --- .../apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java b/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java index 561d1102611..4c1dd621413 100644 --- a/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java +++ b/plugins/acl/dynamic-role-based/src/main/java/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java @@ -111,12 +111,10 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API } protected Account getAccountFromId(long accountId) { - LOGGER.debug("Account not available in cache for-----------------------------" + accountId); return accountService.getAccount(accountId); } protected Pair> getRolePermissions(long roleId) { - LOGGER.debug("RolePermissions not available in cache for role-----------------------------" + roleId); final Role accountRole = roleService.findRole(roleId); if (accountRole == null || accountRole.getId() < 1L) { return new Pair<>(null, null); From a5d02665b4e1d87c54c831192c599e4af7db4328 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 7 Oct 2024 16:21:06 +0530 Subject: [PATCH 42/62] changes for host reqrieval from db Signed-off-by: Abhishek Kumar --- .../com/cloud/capacity/CapacityManager.java | 4 +- .../com/cloud/resource/ResourceManager.java | 2 +- .../manager/ClusteredAgentManagerImpl.java | 17 ++++--- .../main/java/com/cloud/host/dao/HostDao.java | 2 + .../java/com/cloud/host/dao/HostDaoImpl.java | 12 +++++ .../cloud/capacity/CapacityManagerImpl.java | 44 +++++++++---------- .../deploy/DeploymentPlanningManagerImpl.java | 20 +++++---- .../network/as/AutoScaleManagerImpl.java | 2 +- .../cloud/resource/ResourceManagerImpl.java | 20 ++++----- .../RollingMaintenanceManagerImpl.java | 2 +- .../java/com/cloud/vm/UserVmManagerImpl.java | 2 +- .../DeploymentPlanningManagerImplTest.java | 2 +- .../network/as/AutoScaleManagerImplTest.java | 9 ++-- .../resource/MockResourceManagerImpl.java | 2 +- 14 files changed, 78 insertions(+), 62 deletions(-) diff --git a/engine/components-api/src/main/java/com/cloud/capacity/CapacityManager.java b/engine/components-api/src/main/java/com/cloud/capacity/CapacityManager.java index 0f35fbe977e..aaac4857f58 100644 --- a/engine/components-api/src/main/java/com/cloud/capacity/CapacityManager.java +++ b/engine/components-api/src/main/java/com/cloud/capacity/CapacityManager.java @@ -146,12 +146,12 @@ public interface CapacityManager { /** * Check if specified host has capability to support cpu cores and speed freq - * @param hostId the host to be checked + * @param host the host to be checked * @param cpuNum cpu number to check * @param cpuSpeed cpu Speed to check * @return true if the count of host's running VMs >= hypervisor limit */ - boolean checkIfHostHasCpuCapability(long hostId, Integer cpuNum, Integer cpuSpeed); + boolean checkIfHostHasCpuCapability(Host host, Integer cpuNum, Integer cpuSpeed); /** * Check if cluster will cross threshold if the cpu/memory requested are accommodated diff --git a/engine/components-api/src/main/java/com/cloud/resource/ResourceManager.java b/engine/components-api/src/main/java/com/cloud/resource/ResourceManager.java index 235ed46784d..613761a6811 100755 --- a/engine/components-api/src/main/java/com/cloud/resource/ResourceManager.java +++ b/engine/components-api/src/main/java/com/cloud/resource/ResourceManager.java @@ -138,7 +138,7 @@ public interface ResourceManager extends ResourceService, Configurable { public HostVO findHostByName(String name); - HostStats getHostStatistics(long hostId); + HostStats getHostStatistics(Host host); Long getGuestOSCategoryId(long hostId); diff --git a/engine/orchestration/src/main/java/com/cloud/agent/manager/ClusteredAgentManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/agent/manager/ClusteredAgentManagerImpl.java index 749a738e63e..107a3d8ae7b 100644 --- a/engine/orchestration/src/main/java/com/cloud/agent/manager/ClusteredAgentManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/agent/manager/ClusteredAgentManagerImpl.java @@ -250,14 +250,13 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust return new ClusteredAgentHandler(type, link, data); } - protected AgentAttache createAttache(final long id) { - s_logger.debug("create forwarding ClusteredAgentAttache for " + id); - final HostVO host = _hostDao.findById(id); - final AgentAttache attache = new ClusteredAgentAttache(this, id, host.getName()); + protected AgentAttache createAttache(final Host host) { + s_logger.debug("create forwarding ClusteredAgentAttache for " + host.getId()); + final AgentAttache attache = new ClusteredAgentAttache(this, host.getId(), host.getName()); AgentAttache old = null; synchronized (_agents) { - old = _agents.get(id); - _agents.put(id, attache); + old = _agents.get(host.getId()); + _agents.put(host.getId(), attache); } if (old != null) { if (s_logger.isDebugEnabled()) { @@ -567,12 +566,12 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust if (s_logger.isDebugEnabled()) { s_logger.debug("Host " + hostId + " has switched to another management server, need to update agent map with a forwarding agent attache"); } - agent = createAttache(hostId); + agent = createAttache(host); } } if (agent == null) { final AgentUnavailableException ex = new AgentUnavailableException("Host with specified id is not in the right state: " + host.getStatus(), hostId); - ex.addProxyObject(_entityMgr.findById(Host.class, hostId).getUuid()); + ex.addProxyObject(host.getUuid()); throw ex; } @@ -1169,7 +1168,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust final ClusteredDirectAgentAttache attache = (ClusteredDirectAgentAttache)_agents.get(hostId); if (attache != null && attache.getQueueSize() == 0 && attache.getNonRecurringListenersSize() == 0) { handleDisconnectWithoutInvestigation(attache, Event.StartAgentRebalance, true, true); - final ClusteredAgentAttache forwardAttache = (ClusteredAgentAttache)createAttache(hostId); + final ClusteredAgentAttache forwardAttache = (ClusteredAgentAttache)createAttache(host); if (forwardAttache == null) { s_logger.warn("Unable to create a forward attache for the host " + hostId + " as a part of rebalance process"); return false; diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java index d47c08822ad..e7bf35ce9d6 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java @@ -177,4 +177,6 @@ public interface HostDao extends GenericDao, StateDao listAllIds(); List listDistinctHypervisorTypes(final Long zoneId); + + List listByIds(final List ids); } diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java index 9841124cc52..7c412df4b78 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java @@ -98,6 +98,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao protected SearchBuilder TypePodDcStatusSearch; + protected SearchBuilder IdsSearch; protected SearchBuilder IdStatusSearch; protected SearchBuilder TypeDcSearch; protected SearchBuilder TypeDcStatusSearch; @@ -246,6 +247,10 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao TypeClusterStatusSearch.and("resourceState", TypeClusterStatusSearch.entity().getResourceState(), SearchCriteria.Op.EQ); TypeClusterStatusSearch.done(); + IdsSearch = createSearchBuilder(); + IdsSearch.and("id", IdsSearch.entity().getId(), SearchCriteria.Op.IN); + IdsSearch.done(); + IdStatusSearch = createSearchBuilder(); IdStatusSearch.and("id", IdStatusSearch.entity().getId(), SearchCriteria.Op.EQ); IdStatusSearch.and("states", IdStatusSearch.entity().getStatus(), SearchCriteria.Op.IN); @@ -1605,4 +1610,11 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao sc.setParameters("type", Type.Routing); return customSearch(sc, null); } + + @Override + public List listByIds(List ids) { + SearchCriteria sc = IdsSearch.create(); + sc.setParameters("id", ids.toArray()); + return search(sc, null); + } } diff --git a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java index 6caa137c003..a35fd5f5889 100644 --- a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java @@ -227,8 +227,8 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, long reservedMem = capacityMemory.getReservedCapacity(); long reservedCpuCore = capacityCpuCore.getReservedCapacity(); long actualTotalCpu = capacityCpu.getTotalCapacity(); - float cpuOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterIdFinal, "cpuOvercommitRatio").getValue()); - float memoryOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterIdFinal, "memoryOvercommitRatio").getValue()); + float cpuOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterIdFinal, VmDetailConstants.CPU_OVER_COMMIT_RATIO).getValue()); + float memoryOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterIdFinal, VmDetailConstants.MEMORY_OVER_COMMIT_RATIO).getValue()); int vmCPU = svo.getCpu() * svo.getSpeed(); int vmCPUCore = svo.getCpu(); long vmMem = svo.getRamSize() * 1024L * 1024L; @@ -302,8 +302,8 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, final long hostId = vm.getHostId(); final HostVO host = _hostDao.findById(hostId); final long clusterId = host.getClusterId(); - final float cpuOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio").getValue()); - final float memoryOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio").getValue()); + final float cpuOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterId, VmDetailConstants.CPU_OVER_COMMIT_RATIO).getValue()); + final float memoryOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(clusterId, VmDetailConstants.MEMORY_OVER_COMMIT_RATIO).getValue()); final ServiceOfferingVO svo = _offeringsDao.findById(vm.getId(), vm.getServiceOfferingId()); @@ -389,13 +389,13 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, ",alloc_from_last:" + fromLastHost); long cluster_id = host.getClusterId(); - ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao.findDetail(cluster_id, "cpuOvercommitRatio"); - ClusterDetailsVO cluster_detail_ram = _clusterDetailsDao.findDetail(cluster_id, "memoryOvercommitRatio"); + ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao.findDetail(cluster_id, VmDetailConstants.CPU_OVER_COMMIT_RATIO); + ClusterDetailsVO cluster_detail_ram = _clusterDetailsDao.findDetail(cluster_id, VmDetailConstants.MEMORY_OVER_COMMIT_RATIO); Float cpuOvercommitRatio = Float.parseFloat(cluster_detail_cpu.getValue()); Float memoryOvercommitRatio = Float.parseFloat(cluster_detail_ram.getValue()); boolean hostHasCpuCapability, hostHasCapacity = false; - hostHasCpuCapability = checkIfHostHasCpuCapability(host.getId(), cpucore, cpuspeed); + hostHasCpuCapability = checkIfHostHasCpuCapability(host, cpucore, cpuspeed); if (hostHasCpuCapability) { // first check from reserved capacity @@ -425,22 +425,20 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, } @Override - public boolean checkIfHostHasCpuCapability(long hostId, Integer cpuNum, Integer cpuSpeed) { - + public boolean checkIfHostHasCpuCapability(Host host, Integer cpuNum, Integer cpuSpeed) { // Check host can support the Cpu Number and Speed. - Host host = _hostDao.findById(hostId); boolean isCpuNumGood = host.getCpus().intValue() >= cpuNum; boolean isCpuSpeedGood = host.getSpeed().intValue() >= cpuSpeed; if (isCpuNumGood && isCpuSpeedGood) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Host: " + hostId + " has cpu capability (cpu:" + host.getCpus() + ", speed:" + host.getSpeed() + - ") to support requested CPU: " + cpuNum + " and requested speed: " + cpuSpeed); + s_logger.debug("Host: " + host.getId() + " has cpu capability (cpu:" + host.getCpus() + ", speed:" + host.getSpeed() + + ") to support requested CPU: " + cpuNum + " and requested speed: " + cpuSpeed); } return true; } else { if (s_logger.isDebugEnabled()) { - s_logger.debug("Host: " + hostId + " doesn't have cpu capability (cpu:" + host.getCpus() + ", speed:" + host.getSpeed() + - ") to support requested CPU: " + cpuNum + " and requested speed: " + cpuSpeed); + s_logger.debug("Host: " + host.getId() + " doesn't have cpu capability (cpu:" + host.getCpus() + ", speed:" + host.getSpeed() + + ") to support requested CPU: " + cpuNum + " and requested speed: " + cpuSpeed); } return false; } @@ -655,8 +653,8 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, } protected Pair getClusterValues(long clusterId) { - return new Pair<>(_clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio"), - _clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio")); + return new Pair<>(_clusterDetailsDao.findDetail(clusterId, VmDetailConstants.CPU_OVER_COMMIT_RATIO), + _clusterDetailsDao.findDetail(clusterId, VmDetailConstants.MEMORY_OVER_COMMIT_RATIO)); } @@ -1077,8 +1075,8 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, capacityCPU.addAnd("podId", SearchCriteria.Op.EQ, server.getPodId()); capacityCPU.addAnd("capacityType", SearchCriteria.Op.EQ, Capacity.CAPACITY_TYPE_CPU); List capacityVOCpus = _capacityDao.search(capacitySC, null); - Float cpuovercommitratio = Float.parseFloat(_clusterDetailsDao.findDetail(server.getClusterId(), "cpuOvercommitRatio").getValue()); - Float memoryOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(server.getClusterId(), "memoryOvercommitRatio").getValue()); + Float cpuovercommitratio = Float.parseFloat(_clusterDetailsDao.findDetail(server.getClusterId(), VmDetailConstants.CPU_OVER_COMMIT_RATIO).getValue()); + Float memoryOvercommitRatio = Float.parseFloat(_clusterDetailsDao.findDetail(server.getClusterId(), VmDetailConstants.MEMORY_OVER_COMMIT_RATIO).getValue()); if (capacityVOCpus != null && !capacityVOCpus.isEmpty()) { CapacityVO CapacityVOCpu = capacityVOCpus.get(0); @@ -1135,9 +1133,9 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, String capacityOverProvisioningName = ""; if (capacityType == Capacity.CAPACITY_TYPE_CPU) { - capacityOverProvisioningName = "cpuOvercommitRatio"; + capacityOverProvisioningName = VmDetailConstants.CPU_OVER_COMMIT_RATIO; } else if (capacityType == Capacity.CAPACITY_TYPE_MEMORY) { - capacityOverProvisioningName = "memoryOvercommitRatio"; + capacityOverProvisioningName = VmDetailConstants.MEMORY_OVER_COMMIT_RATIO; } else { throw new CloudRuntimeException("Invalid capacityType - " + capacityType); } @@ -1179,12 +1177,12 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, int cpu_requested = offering.getCpu() * offering.getSpeed(); long ram_requested = offering.getRamSize() * 1024L * 1024L; Cluster cluster = _clusterDao.findById(host.getClusterId()); - ClusterDetailsVO clusterDetailsCpuOvercommit = _clusterDetailsDao.findDetail(cluster.getId(), "cpuOvercommitRatio"); - ClusterDetailsVO clusterDetailsRamOvercommmt = _clusterDetailsDao.findDetail(cluster.getId(), "memoryOvercommitRatio"); + ClusterDetailsVO clusterDetailsCpuOvercommit = _clusterDetailsDao.findDetail(cluster.getId(), VmDetailConstants.CPU_OVER_COMMIT_RATIO); + ClusterDetailsVO clusterDetailsRamOvercommmt = _clusterDetailsDao.findDetail(cluster.getId(), VmDetailConstants.MEMORY_OVER_COMMIT_RATIO); Float cpuOvercommitRatio = Float.parseFloat(clusterDetailsCpuOvercommit.getValue()); Float memoryOvercommitRatio = Float.parseFloat(clusterDetailsRamOvercommmt.getValue()); - boolean hostHasCpuCapability = checkIfHostHasCpuCapability(host.getId(), offering.getCpu(), offering.getSpeed()); + boolean hostHasCpuCapability = checkIfHostHasCpuCapability(host, offering.getCpu(), offering.getSpeed()); boolean hostHasCapacity = checkIfHostHasCapacity(host.getId(), cpu_requested, ram_requested, false, cpuOvercommitRatio, memoryOvercommitRatio, considerReservedCapacity); diff --git a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java index d6f32d2f962..62d2333df1e 100644 --- a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -27,6 +27,7 @@ import java.util.Optional; import java.util.Set; import java.util.Timer; import java.util.TreeSet; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; @@ -143,6 +144,7 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Event; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.VmDetailConstants; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; @@ -443,14 +445,14 @@ StateListener, Configurable { if (checkVmProfileAndHost(vmProfile, host)) { long cluster_id = host.getClusterId(); ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao.findDetail(cluster_id, - "cpuOvercommitRatio"); + VmDetailConstants.CPU_OVER_COMMIT_RATIO); ClusterDetailsVO cluster_detail_ram = _clusterDetailsDao.findDetail(cluster_id, - "memoryOvercommitRatio"); + VmDetailConstants.MEMORY_OVER_COMMIT_RATIO); Float cpuOvercommitRatio = Float.parseFloat(cluster_detail_cpu.getValue()); Float memoryOvercommitRatio = Float.parseFloat(cluster_detail_ram.getValue()); boolean hostHasCpuCapability, hostHasCapacity = false; - hostHasCpuCapability = _capacityMgr.checkIfHostHasCpuCapability(host.getId(), offering.getCpu(), offering.getSpeed()); + hostHasCpuCapability = _capacityMgr.checkIfHostHasCpuCapability(host, offering.getCpu(), offering.getSpeed()); if (hostHasCpuCapability) { // first check from reserved capacity @@ -1063,11 +1065,13 @@ StateListener, Configurable { private void checkHostReservations() { List reservedHosts = _plannerHostReserveDao.listAllReservedHosts(); - - for (PlannerHostReservationVO hostReservation : reservedHosts) { - HostVO host = _hostDao.findById(hostReservation.getHostId()); + List hosts = _hostDao.listByIds(reservedHosts + .stream() + .map(PlannerHostReservationVO::getHostId) + .collect(Collectors.toList())); + for (HostVO host : hosts) { if (host != null && host.getManagementServerId() != null && host.getManagementServerId() == _nodeId) { - checkHostReservationRelease(hostReservation.getHostId()); + checkHostReservationRelease(host.getId()); } } @@ -1254,7 +1258,7 @@ StateListener, Configurable { Pair> potentialResources = findPotentialDeploymentResources(suitableHosts, suitableVolumeStoragePools, avoid, resourceUsageRequired, readyAndReusedVolumes, plan.getPreferredHosts(), vmProfile.getVirtualMachine()); if (potentialResources != null) { - Host host = _hostDao.findById(potentialResources.first().getId()); + Host host = potentialResources.first(); Map storageVolMap = potentialResources.second(); // remove the reused vol<->pool from destination, since // we don't have to prepare this volume. diff --git a/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java b/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java index 9beff6555ca..a8bf3bbe292 100644 --- a/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java +++ b/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java @@ -2707,7 +2707,7 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage return vmStatsById; } try { - vmStatsById = virtualMachineManager.getVirtualMachineStatistics(host.getId(), host.getName(), vmIds); + vmStatsById = virtualMachineManager.getVirtualMachineStatistics(host, vmIds); if (MapUtils.isEmpty(vmStatsById)) { s_logger.warn("Got empty result for virtual machine statistics from host: " + host); } diff --git a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java index f9189d2ff52..bf5b4592fae 100755 --- a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java @@ -547,8 +547,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, details.put("ovm3pool", allParams.get("ovm3pool")); details.put("ovm3cluster", allParams.get("ovm3cluster")); } - details.put("cpuOvercommitRatio", CapacityManager.CpuOverprovisioningFactor.value().toString()); - details.put("memoryOvercommitRatio", CapacityManager.MemOverprovisioningFactor.value().toString()); + details.put(VmDetailConstants.CPU_OVER_COMMIT_RATIO, CapacityManager.CpuOverprovisioningFactor.value().toString()); + details.put(VmDetailConstants.MEMORY_OVER_COMMIT_RATIO, CapacityManager.MemOverprovisioningFactor.value().toString()); _clusterDetailsDao.persist(cluster.getId(), details); return result; } @@ -558,8 +558,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, details.put("url", url); details.put("username", StringUtils.defaultString(username)); details.put("password", StringUtils.defaultString(password)); - details.put("cpuOvercommitRatio", CapacityManager.CpuOverprovisioningFactor.value().toString()); - details.put("memoryOvercommitRatio", CapacityManager.MemOverprovisioningFactor.value().toString()); + details.put(VmDetailConstants.CPU_OVER_COMMIT_RATIO, CapacityManager.CpuOverprovisioningFactor.value().toString()); + details.put(VmDetailConstants.MEMORY_OVER_COMMIT_RATIO, CapacityManager.MemOverprovisioningFactor.value().toString()); _clusterDetailsDao.persist(cluster.getId(), details); boolean success = false; @@ -778,9 +778,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } clusterId = cluster.getId(); - if (_clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio") == null) { - final ClusterDetailsVO cluster_cpu_detail = new ClusterDetailsVO(clusterId, "cpuOvercommitRatio", "1"); - final ClusterDetailsVO cluster_memory_detail = new ClusterDetailsVO(clusterId, "memoryOvercommitRatio", "1"); + if (_clusterDetailsDao.findDetail(clusterId, VmDetailConstants.CPU_OVER_COMMIT_RATIO) == null) { + final ClusterDetailsVO cluster_cpu_detail = new ClusterDetailsVO(clusterId, VmDetailConstants.CPU_OVER_COMMIT_RATIO, "1"); + final ClusterDetailsVO cluster_memory_detail = new ClusterDetailsVO(clusterId, VmDetailConstants.MEMORY_OVER_COMMIT_RATIO, "1"); _clusterDetailsDao.persist(cluster_cpu_detail); _clusterDetailsDao.persist(cluster_memory_detail); } @@ -3287,15 +3287,15 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } @Override - public HostStats getHostStatistics(final long hostId) { - final Answer answer = _agentMgr.easySend(hostId, new GetHostStatsCommand(_hostDao.findById(hostId).getGuid(), _hostDao.findById(hostId).getName(), hostId)); + public HostStats getHostStatistics(final Host host) { + final Answer answer = _agentMgr.easySend(host.getId(), new GetHostStatsCommand(host.getGuid(), host.getName(), host.getId())); if (answer != null && answer instanceof UnsupportedAnswer) { return null; } if (answer == null || !answer.getResult()) { - final String msg = "Unable to obtain host " + hostId + " statistics. "; + final String msg = "Unable to obtain host " + host.getId() + " statistics. "; s_logger.warn(msg); return null; } else { diff --git a/server/src/main/java/com/cloud/resource/RollingMaintenanceManagerImpl.java b/server/src/main/java/com/cloud/resource/RollingMaintenanceManagerImpl.java index d881dee137a..581a34e4e13 100644 --- a/server/src/main/java/com/cloud/resource/RollingMaintenanceManagerImpl.java +++ b/server/src/main/java/com/cloud/resource/RollingMaintenanceManagerImpl.java @@ -637,7 +637,7 @@ public class RollingMaintenanceManagerImpl extends ManagerBase implements Rollin continue; } boolean maxGuestLimit = capacityManager.checkIfHostReachMaxGuestLimit(host); - boolean hostHasCPUCapacity = capacityManager.checkIfHostHasCpuCapability(hostInCluster.getId(), serviceOffering.getCpu(), serviceOffering.getSpeed()); + boolean hostHasCPUCapacity = capacityManager.checkIfHostHasCpuCapability(hostInCluster, serviceOffering.getCpu(), serviceOffering.getSpeed()); int cpuRequested = serviceOffering.getCpu() * serviceOffering.getSpeed(); long ramRequested = serviceOffering.getRamSize() * 1024L * 1024L; ClusterDetailsVO clusterDetailsCpuOvercommit = clusterDetailsDao.findDetail(cluster.getId(), "cpuOvercommitRatio"); diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 2c822a8b519..7006346df34 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -2010,7 +2010,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // #1 Check existing host has capacity & and the correct tags if (!excludes.shouldAvoid(ApiDBUtils.findHostById(vmInstance.getHostId()))) { - existingHostHasCapacity = _capacityMgr.checkIfHostHasCpuCapability(vmInstance.getHostId(), newCpu, newSpeed) + existingHostHasCapacity = _capacityMgr.checkIfHostHasCpuCapability(host, newCpu, newSpeed) && _capacityMgr.checkIfHostHasCapacity(vmInstance.getHostId(), cpuDiff, ByteScaleUtils.mebibytesToBytes(memoryDiff), false, _capacityMgr.getClusterOverProvisioningFactor(host.getClusterId(), Capacity.CAPACITY_TYPE_CPU), _capacityMgr.getClusterOverProvisioningFactor(host.getClusterId(), Capacity.CAPACITY_TYPE_MEMORY), false) diff --git a/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java b/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java index 528108da6a7..679169394e9 100644 --- a/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java +++ b/server/src/test/java/com/cloud/deploy/DeploymentPlanningManagerImplTest.java @@ -864,7 +864,7 @@ public class DeploymentPlanningManagerImplTest { Pair> potentialResources = new Pair<>(host, suitableVolumeStoragePoolMap); Mockito.when(capacityMgr.checkIfHostReachMaxGuestLimit(host)).thenReturn(false); - Mockito.when(capacityMgr.checkIfHostHasCpuCapability(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())).thenReturn(true); + Mockito.when(capacityMgr.checkIfHostHasCpuCapability(ArgumentMatchers.any(Host.class), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())).thenReturn(true); Mockito.when(capacityMgr.checkIfHostHasCapacity( ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt(), diff --git a/server/src/test/java/com/cloud/network/as/AutoScaleManagerImplTest.java b/server/src/test/java/com/cloud/network/as/AutoScaleManagerImplTest.java index 713f4efdbff..dc733531dfe 100644 --- a/server/src/test/java/com/cloud/network/as/AutoScaleManagerImplTest.java +++ b/server/src/test/java/com/cloud/network/as/AutoScaleManagerImplTest.java @@ -100,6 +100,7 @@ import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceInUseException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.network.Network; @@ -2279,13 +2280,13 @@ public class AutoScaleManagerImplTest { public void getVmStatsByIdFromHost() { List vmIds = Mockito.mock(ArrayList.class); Map vmStatsById = Mockito.mock(HashMap.class); - Mockito.doReturn(vmStatsById).when(virtualMachineManager).getVirtualMachineStatistics(anyLong(), anyString(), anyList()); + Mockito.doReturn(vmStatsById).when(virtualMachineManager).getVirtualMachineStatistics(Mockito.any(Host.class), anyList()); Map result = autoScaleManagerImplSpy.getVmStatsByIdFromHost(-1L, vmIds); Assert.assertEquals(0, result.size()); - Mockito.verify(virtualMachineManager, never()).getVirtualMachineStatistics(anyLong(), anyString(), anyList()); + Mockito.verify(virtualMachineManager, never()).getVirtualMachineStatistics(Mockito.any(Host.class), anyList()); } @Test @@ -2297,13 +2298,13 @@ public class AutoScaleManagerImplTest { when(hostDao.findById(hostId)).thenReturn(hostMock); when(hostMock.getId()).thenReturn(hostId); when(hostMock.getName()).thenReturn(hostName); - Mockito.doReturn(vmStatsById).when(virtualMachineManager).getVirtualMachineStatistics(anyLong(), anyString(), anyList()); + Mockito.doReturn(vmStatsById).when(virtualMachineManager).getVirtualMachineStatistics(Mockito.any(Host.class), anyList()); Map result = autoScaleManagerImplSpy.getVmStatsByIdFromHost(hostId, vmIds); Assert.assertEquals(vmStatsById, result); - Mockito.verify(virtualMachineManager).getVirtualMachineStatistics(anyLong(), anyString(), anyList()); + Mockito.verify(virtualMachineManager).getVirtualMachineStatistics(Mockito.any(Host.class), anyList()); } @Test diff --git a/server/src/test/java/com/cloud/resource/MockResourceManagerImpl.java b/server/src/test/java/com/cloud/resource/MockResourceManagerImpl.java index 5bb0ff971a8..a89fda38685 100755 --- a/server/src/test/java/com/cloud/resource/MockResourceManagerImpl.java +++ b/server/src/test/java/com/cloud/resource/MockResourceManagerImpl.java @@ -465,7 +465,7 @@ public class MockResourceManagerImpl extends ManagerBase implements ResourceMana * @see com.cloud.resource.ResourceManager#getHostStatistics(long) */ @Override - public HostStats getHostStatistics(final long hostId) { + public HostStats getHostStatistics(final Host host) { // TODO Auto-generated method stub return null; } From a9661f45877a71c9763a2d23583c9dca3811c443 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 7 Oct 2024 16:23:15 +0530 Subject: [PATCH 43/62] changes in statscollection Signed-off-by: Abhishek Kumar --- .../com/cloud/vm/VirtualMachineManager.java | 16 ++- .../cloud/vm/VirtualMachineManagerImpl.java | 48 ++++----- .../java/com/cloud/vm/dao/VMInstanceDao.java | 8 +- .../com/cloud/vm/dao/VMInstanceDaoImpl.java | 29 ++++- .../java/com/cloud/server/StatsCollector.java | 101 ++++++++++-------- 5 files changed, 116 insertions(+), 86 deletions(-) diff --git a/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java b/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java index fc2afd65cd7..36e083683ca 100644 --- a/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java +++ b/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java @@ -275,24 +275,22 @@ public interface VirtualMachineManager extends Manager { /** * Obtains statistics for a list of VMs; CPU and network utilization - * @param hostId ID of the host - * @param hostName name of the host + * @param host host * @param vmIds list of VM IDs * @return map of VM ID and stats entry for the VM */ - HashMap getVirtualMachineStatistics(long hostId, String hostName, List vmIds); + HashMap getVirtualMachineStatistics(Host host, List vmIds); /** * Obtains statistics for a list of VMs; CPU and network utilization - * @param hostId ID of the host - * @param hostName name of the host - * @param vmMap map of VM IDs and the corresponding VirtualMachine object + * @param host host + * @param vmMap map of VM instanceName and its ID * @return map of VM ID and stats entry for the VM */ - HashMap getVirtualMachineStatistics(long hostId, String hostName, Map vmMap); + HashMap getVirtualMachineStatistics(Host host, Map vmMap); - HashMap> getVmDiskStatistics(long hostId, String hostName, Map vmMap); + HashMap> getVmDiskStatistics(Host host, Map vmInstanceNameIdMap); - HashMap> getVmNetworkStatistics(long hostId, String hostName, Map vmMap); + HashMap> getVmNetworkStatistics(Host host, Map vmInstanceNameIdMap); Map getDiskOfferingSuitabilityForVm(long vmId, List diskOfferingIds); diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index a56d3205c20..4fc3041bb25 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -5981,29 +5981,23 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @Override - public HashMap getVirtualMachineStatistics(long hostId, String hostName, List vmIds) { + public HashMap getVirtualMachineStatistics(Host host, List vmIds) { HashMap vmStatsById = new HashMap<>(); if (CollectionUtils.isEmpty(vmIds)) { return vmStatsById; } - Map vmMap = new HashMap<>(); - for (Long vmId : vmIds) { - vmMap.put(vmId, _vmDao.findById(vmId)); - } - return getVirtualMachineStatistics(hostId, hostName, vmMap); + Map vmMap = _vmDao.getNameIdMapForVmIds(vmIds); + return getVirtualMachineStatistics(host, vmMap); } @Override - public HashMap getVirtualMachineStatistics(long hostId, String hostName, Map vmMap) { + public HashMap getVirtualMachineStatistics(Host host, Map vmInstanceNameIdMap) { HashMap vmStatsById = new HashMap<>(); - if (MapUtils.isEmpty(vmMap)) { + if (MapUtils.isEmpty(vmInstanceNameIdMap)) { return vmStatsById; } - Map vmNames = new HashMap<>(); - for (Map.Entry vmEntry : vmMap.entrySet()) { - vmNames.put(vmEntry.getValue().getInstanceName(), vmEntry.getKey()); - } - Answer answer = _agentMgr.easySend(hostId, new GetVmStatsCommand(new ArrayList<>(vmNames.keySet()), _hostDao.findById(hostId).getGuid(), hostName)); + Answer answer = _agentMgr.easySend(host.getId(), new GetVmStatsCommand( + new ArrayList<>(vmInstanceNameIdMap.keySet()), host.getGuid(), host.getName())); if (answer == null || !answer.getResult()) { s_logger.warn("Unable to obtain VM statistics."); return vmStatsById; @@ -6014,23 +6008,20 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return vmStatsById; } for (Map.Entry entry : vmStatsByName.entrySet()) { - vmStatsById.put(vmNames.get(entry.getKey()), entry.getValue()); + vmStatsById.put(vmInstanceNameIdMap.get(entry.getKey()), entry.getValue()); } } return vmStatsById; } @Override - public HashMap> getVmDiskStatistics(long hostId, String hostName, Map vmMap) { + public HashMap> getVmDiskStatistics(Host host, Map vmInstanceNameIdMap) { HashMap> vmDiskStatsById = new HashMap<>(); - if (MapUtils.isEmpty(vmMap)) { + if (MapUtils.isEmpty(vmInstanceNameIdMap)) { return vmDiskStatsById; } - Map vmNames = new HashMap<>(); - for (Map.Entry vmEntry : vmMap.entrySet()) { - vmNames.put(vmEntry.getValue().getInstanceName(), vmEntry.getKey()); - } - Answer answer = _agentMgr.easySend(hostId, new GetVmDiskStatsCommand(new ArrayList<>(vmNames.keySet()), _hostDao.findById(hostId).getGuid(), hostName)); + Answer answer = _agentMgr.easySend(host.getId(), new GetVmDiskStatsCommand( + new ArrayList<>(vmInstanceNameIdMap.keySet()), host.getGuid(), host.getName())); if (answer == null || !answer.getResult()) { s_logger.warn("Unable to obtain VM disk statistics."); return vmDiskStatsById; @@ -6041,23 +6032,20 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return vmDiskStatsById; } for (Map.Entry> entry: vmDiskStatsByName.entrySet()) { - vmDiskStatsById.put(vmNames.get(entry.getKey()), entry.getValue()); + vmDiskStatsById.put(vmInstanceNameIdMap.get(entry.getKey()), entry.getValue()); } } return vmDiskStatsById; } @Override - public HashMap> getVmNetworkStatistics(long hostId, String hostName, Map vmMap) { + public HashMap> getVmNetworkStatistics(Host host, Map vmInstanceNameIdMap) { HashMap> vmNetworkStatsById = new HashMap<>(); - if (MapUtils.isEmpty(vmMap)) { + if (MapUtils.isEmpty(vmInstanceNameIdMap)) { return vmNetworkStatsById; } - Map vmNames = new HashMap<>(); - for (Map.Entry vmEntry : vmMap.entrySet()) { - vmNames.put(vmEntry.getValue().getInstanceName(), vmEntry.getKey()); - } - Answer answer = _agentMgr.easySend(hostId, new GetVmNetworkStatsCommand(new ArrayList<>(vmNames.keySet()), _hostDao.findById(hostId).getGuid(), hostName)); + Answer answer = _agentMgr.easySend(host.getId(), new GetVmNetworkStatsCommand( + new ArrayList<>(vmInstanceNameIdMap.keySet()), host.getGuid(), host.getName())); if (answer == null || !answer.getResult()) { s_logger.warn("Unable to obtain VM network statistics."); return vmNetworkStatsById; @@ -6068,7 +6056,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return vmNetworkStatsById; } for (Map.Entry> entry: vmNetworkStatsByName.entrySet()) { - vmNetworkStatsById.put(vmNames.get(entry.getKey()), entry.getValue()); + vmNetworkStatsById.put(vmInstanceNameIdMap.get(entry.getKey()), entry.getValue()); } } return vmNetworkStatsById; diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java index a840c422212..ce47e9c5276 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java @@ -16,10 +16,12 @@ // under the License. package com.cloud.vm.dao; +import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import com.cloud.hypervisor.Hypervisor; import com.cloud.utils.Pair; @@ -144,7 +146,7 @@ public interface VMInstanceDao extends GenericDao, StateDao< */ List listDistinctHostNames(long networkId, VirtualMachine.Type... types); - List findByHostInStatesExcluding(Long hostId, List excludingIds, State... states); + List findByHostInStatesExcluding(Long hostId, Set excludingIds, State... states); List findByHostInStates(Long hostId, State... states); @@ -176,4 +178,8 @@ public interface VMInstanceDao extends GenericDao, StateDao< List listIdServiceOfferingForVmsByLastHostId(Long hostId); + Map getNameIdMapForVmInstanceNames(Collection names); + + Map getNameIdMapForVmIds(Collection ids); + } diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java index ef436a47d39..8eeb79e8683 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -20,10 +20,13 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.PostConstruct; import javax.inject.Inject; @@ -893,7 +896,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem } @Override - public List findByHostInStatesExcluding(Long hostId, List excludingIds, State... states) { + public List findByHostInStatesExcluding(Long hostId, Set excludingIds, State... states) { SearchCriteria sc = HostAndStateSearch.create(); sc.setParameters("host", hostId); if (excludingIds != null && !excludingIds.isEmpty()) { @@ -1084,4 +1087,28 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem sc.setParameters("state", State.Stopped); return customSearch(sc, null); } + + @Override + public Map getNameIdMapForVmInstanceNames(Collection names) { + SearchBuilder sb = createSearchBuilder(); + sb.and("name", sb.entity().getInstanceName(), Op.IN); + sb.selectFields(sb.entity().getId(), sb.entity().getInstanceName()); + SearchCriteria sc = sb.create(); + sc.setParameters("name", names.toArray()); + List vms = customSearch(sc, null); + return vms.stream() + .collect(Collectors.toMap(VMInstanceVO::getInstanceName, VMInstanceVO::getId)); + } + + @Override + public Map getNameIdMapForVmIds(Collection ids) { + SearchBuilder sb = createSearchBuilder(); + sb.and("id", sb.entity().getId(), Op.IN); + sb.selectFields(sb.entity().getId(), sb.entity().getInstanceName()); + SearchCriteria sc = sb.create(); + sc.setParameters("id", ids.toArray()); + List vms = customSearch(sc, null); + return vms.stream() + .collect(Collectors.toMap(VMInstanceVO::getInstanceName, VMInstanceVO::getId)); + } } diff --git a/server/src/main/java/com/cloud/server/StatsCollector.java b/server/src/main/java/com/cloud/server/StatsCollector.java index 5eb0e048f17..2eb831cd973 100644 --- a/server/src/main/java/com/cloud/server/StatsCollector.java +++ b/server/src/main/java/com/cloud/server/StatsCollector.java @@ -41,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import javax.inject.Inject; @@ -131,6 +132,7 @@ import com.cloud.user.dao.UserStatisticsDao; import com.cloud.user.dao.VmDiskStatisticsDao; import com.cloud.utils.LogUtils; import com.cloud.utils.NumbersUtil; +import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentMethodInterceptable; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -147,7 +149,6 @@ import com.cloud.utils.net.MacAddress; import com.cloud.utils.script.Script; import com.cloud.vm.NicVO; import com.cloud.vm.UserVmManager; -import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineManager; @@ -627,17 +628,21 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc externalStatsPrefix, externalStatsHost, externalStatsPort)); } - protected Map getVmMapForStatsForHost(Host host) { + protected Pair, Map> getVmMapForStatsForHost(Host host) { List vms = _vmInstance.listByHostAndState(host.getId(), VirtualMachine.State.Running); boolean collectUserVMStatsOnly = Boolean.TRUE.equals(vmStatsCollectUserVMOnly.value()); - Map vmMap = new HashMap<>(); - for (VMInstanceVO vm : vms) { - if (collectUserVMStatsOnly && !VirtualMachine.Type.User.equals(vm.getType())) { - continue; - } - vmMap.put(vm.getId(), vm); + if (collectUserVMStatsOnly) { + vms = vms.stream().filter(vm -> VirtualMachine.Type.User.equals(vm.getType())).collect(Collectors.toList()); } - return vmMap; + Map idInstanceMap = new HashMap<>(); + Map instanceNameIdMap = new HashMap<>(); + vms.forEach(vm -> { + if (!collectUserVMStatsOnly || VirtualMachine.Type.User.equals(vm.getType())) { + idInstanceMap.put(vm.getId(), vm); + instanceNameIdMap.put(vm.getInstanceName(), vm.getId()); + } + }); + return new Pair<>(idInstanceMap, instanceNameIdMap); } class HostCollector extends AbstractStatsCollector { @@ -652,7 +657,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc List hosts = _hostDao.search(sc, null); for (HostVO host : hosts) { - HostStatsEntry hostStatsEntry = (HostStatsEntry) _resourceMgr.getHostStatistics(host.getId()); + HostStatsEntry hostStatsEntry = (HostStatsEntry) _resourceMgr.getHostStatistics(host); if (hostStatsEntry != null) { hostStatsEntry.setHostVo(host); metrics.put(hostStatsEntry.getHostId(), hostStatsEntry); @@ -1201,37 +1206,39 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc for (HostVO host : hosts) { Date timestamp = new Date(); - Map vmMap = getVmMapForStatsForHost(host); + Pair, Map> vmsAndMap = getVmMapForStatsForHost(host); + Map vmMap = vmsAndMap.first(); try { - Map vmStatsById = virtualMachineManager.getVirtualMachineStatistics(host.getId(), host.getName(), vmMap); - - if (vmStatsById != null) { - Set vmIdSet = vmStatsById.keySet(); - for (Long vmId : vmIdSet) { - VmStatsEntry statsForCurrentIteration = (VmStatsEntry)vmStatsById.get(vmId); - statsForCurrentIteration.setVmId(vmId); - VMInstanceVO vm = vmMap.get(vmId); - statsForCurrentIteration.setVmUuid(vm.getUuid()); - - persistVirtualMachineStats(statsForCurrentIteration, timestamp); - - if (externalStatsType == ExternalStatsProtocol.GRAPHITE) { - prepareVmMetricsForGraphite(metrics, statsForCurrentIteration); - } else { - metrics.put(statsForCurrentIteration.getVmId(), statsForCurrentIteration); - } - } - - if (!metrics.isEmpty()) { - if (externalStatsType == ExternalStatsProtocol.GRAPHITE) { - sendVmMetricsToGraphiteHost(metrics, host); - } else if (externalStatsType == ExternalStatsProtocol.INFLUXDB) { - sendMetricsToInfluxdb(metrics); - } - } - - metrics.clear(); + Map vmStatsById = virtualMachineManager.getVirtualMachineStatistics( + host, vmsAndMap.second()); + if (MapUtils.isEmpty(vmStatsById)) { + continue; } + Set vmIdSet = vmStatsById.keySet(); + for (Long vmId : vmIdSet) { + VmStatsEntry statsForCurrentIteration = (VmStatsEntry)vmStatsById.get(vmId); + statsForCurrentIteration.setVmId(vmId); + VMInstanceVO vm = vmMap.get(vmId); + statsForCurrentIteration.setVmUuid(vm.getUuid()); + + persistVirtualMachineStats(statsForCurrentIteration, timestamp); + + if (externalStatsType == ExternalStatsProtocol.GRAPHITE) { + prepareVmMetricsForGraphite(metrics, statsForCurrentIteration); + } else { + metrics.put(statsForCurrentIteration.getVmId(), statsForCurrentIteration); + } + } + + if (!metrics.isEmpty()) { + if (externalStatsType == ExternalStatsProtocol.GRAPHITE) { + sendVmMetricsToGraphiteHost(metrics, host); + } else if (externalStatsType == ExternalStatsProtocol.INFLUXDB) { + sendMetricsToInfluxdb(metrics); + } + } + + metrics.clear(); } catch (Exception e) { LOGGER.debug("Failed to get VM stats for host with ID: " + host.getId()); continue; @@ -1419,8 +1426,10 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - Map vmMap = getVmMapForStatsForHost(host); - HashMap> vmDiskStatsById = virtualMachineManager.getVmDiskStatistics(host.getId(), host.getName(), vmMap); + Pair, Map> vmsAndMap = getVmMapForStatsForHost(host); + Map vmMap = vmsAndMap.first(); + HashMap> vmDiskStatsById = + virtualMachineManager.getVmDiskStatistics(host, vmsAndMap.second()); if (vmDiskStatsById == null) return; @@ -1527,8 +1536,10 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - Map vmMap = getVmMapForStatsForHost(host); - HashMap> vmNetworkStatsById = virtualMachineManager.getVmNetworkStatistics(host.getId(), host.getName(), vmMap); + Pair, Map> vmsAndMap = getVmMapForStatsForHost(host); + Map vmMap = vmsAndMap.first(); + HashMap> vmNetworkStatsById = + virtualMachineManager.getVmNetworkStatistics(host, vmsAndMap.second()); if (vmNetworkStatsById == null) return; @@ -1537,8 +1548,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc List vmNetworkStats = vmNetworkStatsById.get(vmId); if (CollectionUtils.isEmpty(vmNetworkStats)) continue; - UserVmVO userVm = _userVmDao.findById(vmId); - if (userVm == null) { + VMInstanceVO userVm = vmMap.get(vmId); + if (!VirtualMachine.Type.User.equals(userVm.getType())) { LOGGER.debug("Cannot find uservm with id: " + vmId + " , continue"); continue; } From c859f8ba8076314500461d1c2b2eacdce37c3ade Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 7 Oct 2024 16:25:14 +0530 Subject: [PATCH 44/62] changes in vm powerstate sync Signed-off-by: Abhishek Kumar --- .../vm/VirtualMachinePowerStateSyncImpl.java | 189 +++++++++--------- .../java/com/cloud/vm/dao/VMInstanceDao.java | 10 +- .../com/cloud/vm/dao/VMInstanceDaoImpl.java | 100 ++++++++- 3 files changed, 193 insertions(+), 106 deletions(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java index 79e2de4ae57..23c78f7e846 100644 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java @@ -16,23 +16,23 @@ // under the License. package com.cloud.vm; -import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import javax.inject.Inject; import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.PublishScope; +import org.apache.commons.collections.MapUtils; import org.apache.log4j.Logger; import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.configuration.ManagementServiceConfiguration; import com.cloud.utils.DateUtil; -import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.dao.VMInstanceDao; public class VirtualMachinePowerStateSyncImpl implements VirtualMachinePowerStateSync { @@ -68,106 +68,108 @@ public class VirtualMachinePowerStateSyncImpl implements VirtualMachinePowerStat processReport(hostId, translatedInfo, force); } - private void processReport(long hostId, Map translatedInfo, boolean force) { - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Process VM state report. host: " + hostId + ", number of records in report: " + translatedInfo.size()); + private void updateAndPublishVmPowerStates(long hostId, Map instancePowerStates, + Date updateTime) { + if (instancePowerStates.isEmpty()) { + return; } - - for (Map.Entry entry : translatedInfo.entrySet()) { - - if (s_logger.isDebugEnabled()) - s_logger.debug("VM state report. host: " + hostId + ", vm id: " + entry.getKey() + ", power state: " + entry.getValue()); - - if (_instanceDao.updatePowerState(entry.getKey(), hostId, entry.getValue(), DateUtil.currentGMTTime())) { - if (s_logger.isInfoEnabled()) { - s_logger.debug("VM state report is updated. host: " + hostId + ", vm id: " + entry.getKey() + ", power state: " + entry.getValue()); + Set vmIds = instancePowerStates.keySet(); + Map notUpdated = _instanceDao.updatePowerState(instancePowerStates, hostId, + updateTime); + if (notUpdated.size() <= vmIds.size()) { + for (Long vmId : vmIds) { + if (!notUpdated.isEmpty() && !notUpdated.containsKey(vmId)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("VM state report is updated. host: %d, vm id: %d, power state: %s", + hostId, vmId, instancePowerStates.get(vmId))); + } + _messageBus.publish(null, VirtualMachineManager.Topics.VM_POWER_STATE, + PublishScope.GLOBAL, vmId); + continue; } - - _messageBus.publish(null, VirtualMachineManager.Topics.VM_POWER_STATE, PublishScope.GLOBAL, entry.getKey()); - } else { if (s_logger.isTraceEnabled()) { - s_logger.trace("VM power state does not change, skip DB writing. vm id: " + entry.getKey()); + s_logger.trace(String.format("VM power state does not change, skip DB writing. vm id: %d", vmId)); } } } + } + private void processMissingVmReport(long hostId, Set vmIds, boolean force) { // any state outdates should be checked against the time before this list was retrieved Date startTime = DateUtil.currentGMTTime(); // for all running/stopping VMs, we provide monitoring of missing report - // FIXME: CPU & DB hotspot findByHostInStatesExcluding - List vmsThatAreMissingReport = _instanceDao.findByHostInStatesExcluding(hostId, new ArrayList<>(translatedInfo.keySet()), + List vmsThatAreMissingReport = _instanceDao.findByHostInStatesExcluding(hostId, vmIds, VirtualMachine.State.Running, VirtualMachine.State.Stopping, VirtualMachine.State.Starting); - // here we need to be wary of out of band migration as opposed to other, more unexpected state changes - if (vmsThatAreMissingReport.size() > 0) { - Date currentTime = DateUtil.currentGMTTime(); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Run missing VM report. current time: " + currentTime.getTime()); - } + if (vmsThatAreMissingReport.isEmpty()) { + return; + } + Date currentTime = DateUtil.currentGMTTime(); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Run missing VM report. current time: " + currentTime.getTime()); + } + if (!force) { + List outdatedVms = vmsThatAreMissingReport.stream() + .filter(v -> !_instanceDao.isPowerStateUpToDate(v)) + .map(VMInstanceVO::getId) + .collect(Collectors.toList()); + _instanceDao.resetVmPowerStateTracking(outdatedVms); + vmsThatAreMissingReport = vmsThatAreMissingReport.stream() + .filter(v -> !outdatedVms.contains(v.getId())) + .collect(Collectors.toList()); + } - // 2 times of sync-update interval for graceful period - long milliSecondsGracefullPeriod = mgmtServiceConf.getPingInterval() * 2000L; - - for (VMInstanceVO instance : vmsThatAreMissingReport) { - - // Make sure powerState is up to date for missing VMs - try { - if (!force && !_instanceDao.isPowerStateUpToDate(instance.getId())) { - s_logger.warn("Detected missing VM but power state is outdated, wait for another process report run for VM id: " + instance.getId()); - _instanceDao.resetVmPowerStateTracking(instance.getId()); - continue; - } - } catch (CloudRuntimeException e) { - s_logger.warn("Checked for missing powerstate of a none existing vm", e); - continue; - } - - Date vmStateUpdateTime = instance.getPowerStateUpdateTime(); + // 2 times of sync-update interval for graceful period + long milliSecondsGracefulPeriod = mgmtServiceConf.getPingInterval() * 2000L; + Map instancePowerStates = new HashMap<>(); + for (VMInstanceVO instance : vmsThatAreMissingReport) { + Date vmStateUpdateTime = instance.getPowerStateUpdateTime(); + if (vmStateUpdateTime == null) { + s_logger.warn("VM power state update time is null, falling back to update time for vm id: " + instance.getId()); + vmStateUpdateTime = instance.getUpdateTime(); if (vmStateUpdateTime == null) { - s_logger.warn("VM power state update time is null, falling back to update time for vm id: " + instance.getId()); - vmStateUpdateTime = instance.getUpdateTime(); - if (vmStateUpdateTime == null) { - s_logger.warn("VM update time is null, falling back to creation time for vm id: " + instance.getId()); - vmStateUpdateTime = instance.getCreated(); - } + s_logger.warn("VM update time is null, falling back to creation time for vm id: " + instance.getId()); + vmStateUpdateTime = instance.getCreated(); } - - if (s_logger.isInfoEnabled()) { - String lastTime = new SimpleDateFormat("yyyy/MM/dd'T'HH:mm:ss.SSS'Z'").format(vmStateUpdateTime); - s_logger.debug( - String.format("Detected missing VM. host: %d, vm id: %d(%s), power state: %s, last state update: %s" - , hostId - , instance.getId() - , instance.getUuid() - , VirtualMachine.PowerState.PowerReportMissing - , lastTime)); - } - - long milliSecondsSinceLastStateUpdate = currentTime.getTime() - vmStateUpdateTime.getTime(); - - if (force || milliSecondsSinceLastStateUpdate > milliSecondsGracefullPeriod) { - s_logger.debug("vm id: " + instance.getId() + " - time since last state update(" + milliSecondsSinceLastStateUpdate + "ms) has passed graceful period"); - - // this is were a race condition might have happened if we don't re-fetch the instance; - // between the startime of this job and the currentTime of this missing-branch - // an update might have occurred that we should not override in case of out of band migration - if (_instanceDao.updatePowerState(instance.getId(), hostId, VirtualMachine.PowerState.PowerReportMissing, startTime)) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("VM state report is updated. host: " + hostId + ", vm id: " + instance.getId() + ", power state: PowerReportMissing "); - } - - _messageBus.publish(null, VirtualMachineManager.Topics.VM_POWER_STATE, PublishScope.GLOBAL, instance.getId()); - } else { - if (s_logger.isDebugEnabled()) { - s_logger.debug("VM power state does not change, skip DB writing. vm id: " + instance.getId()); - } - } - } else { - s_logger.debug("vm id: " + instance.getId() + " - time since last state update(" + milliSecondsSinceLastStateUpdate + "ms) has not passed graceful period yet"); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug( + String.format("Detected missing VM. host: %d, vm id: %d(%s), power state: %s, last state update: %s" + , hostId + , instance.getId() + , instance.getUuid() + , VirtualMachine.PowerState.PowerReportMissing + , DateUtil.getOutputString(vmStateUpdateTime))); + } + long milliSecondsSinceLastStateUpdate = currentTime.getTime() - vmStateUpdateTime.getTime(); + if (force || (milliSecondsSinceLastStateUpdate > milliSecondsGracefulPeriod)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("vm id: %d - time since last state update(%d ms) has passed graceful period", + instance.getId(), milliSecondsSinceLastStateUpdate)); } + // this is where a race condition might have happened if we don't re-fetch the instance; + // between the startime of this job and the currentTime of this missing-branch + // an update might have occurred that we should not override in case of out of band migration + instancePowerStates.put(instance.getId(), VirtualMachine.PowerState.PowerReportMissing); + } else { + s_logger.debug(String.format("vm id: %d - time since last state update(%d ms) has not passed graceful period yet", + instance.getId(), milliSecondsSinceLastStateUpdate)); } } + updateAndPublishVmPowerStates(hostId, instancePowerStates, startTime); + } + + private void processReport(long hostId, Map translatedInfo, boolean force) { + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("Process VM state report. Host: %d, number of records in report: %d. VMs: [%s]", + hostId, + translatedInfo.size(), + translatedInfo.entrySet().stream().map(entry -> entry.getKey() + ":" + entry.getValue()) + .collect(Collectors.joining(", ")) + "]")); + } + updateAndPublishVmPowerStates(hostId, translatedInfo, DateUtil.currentGMTTime()); + + processMissingVmReport(hostId, translatedInfo.keySet(), force); if (s_logger.isDebugEnabled()) s_logger.debug("Done with process of VM state report. host: " + hostId); @@ -175,24 +177,19 @@ public class VirtualMachinePowerStateSyncImpl implements VirtualMachinePowerStat @Override public Map convertVmStateReport(Map states) { - final HashMap map = new HashMap(); - if (states == null) { + final HashMap map = new HashMap<>(); + if (MapUtils.isEmpty(states)) { return map; } - + Map nameIdMap = _instanceDao.getNameIdMapForVmInstanceNames(states.keySet()); for (Map.Entry entry : states.entrySet()) { - VMInstanceVO vm = findVM(entry.getKey()); - if (vm != null) { - map.put(vm.getId(), entry.getValue().getState()); + Long id = nameIdMap.get(entry.getKey()); + if (id != null) { + map.put(id, entry.getValue().getState()); } else { s_logger.debug("Unable to find matched VM in CloudStack DB. name: " + entry.getKey()); } } - return map; } - - private VMInstanceVO findVM(String vmName) { - return _instanceDao.findVMByInstanceName(vmName); - } } diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java index ce47e9c5276..a92ecabef83 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java @@ -21,7 +21,6 @@ import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import com.cloud.hypervisor.Hypervisor; import com.cloud.utils.Pair; @@ -146,7 +145,7 @@ public interface VMInstanceDao extends GenericDao, StateDao< */ List listDistinctHostNames(long networkId, VirtualMachine.Type... types); - List findByHostInStatesExcluding(Long hostId, Set excludingIds, State... states); + List findByHostInStatesExcluding(Long hostId, Collection excludingIds, State... states); List findByHostInStates(Long hostId, State... states); @@ -154,15 +153,20 @@ public interface VMInstanceDao extends GenericDao, StateDao< boolean updatePowerState(long instanceId, long powerHostId, VirtualMachine.PowerState powerState, Date wisdomEra); + Map updatePowerState(Map instancePowerStates, + long powerHostId, Date wisdomEra); + void resetVmPowerStateTracking(long instanceId); + void resetVmPowerStateTracking(List instanceId); + void resetHostPowerStateTracking(long hostId); HashMap countVgpuVMs(Long dcId, Long podId, Long clusterId); VMInstanceVO findVMByHostNameInZone(String hostName, long zoneId); - boolean isPowerStateUpToDate(long instanceId); + boolean isPowerStateUpToDate(VMInstanceVO instance); List listNonMigratingVmsByHostEqualsLastHost(long hostId); diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java index 8eeb79e8683..79f11e6fb4e 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -25,7 +25,6 @@ import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; import javax.annotation.PostConstruct; @@ -103,6 +102,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem protected SearchBuilder NotMigratingSearch; protected SearchBuilder BackupSearch; protected SearchBuilder LastHostAndStatesSearch; + protected SearchBuilder IdsPowerStateSelectSearch; @Inject ResourceTagDao _tagsDao; @@ -322,6 +322,15 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem LastHostAndStatesSearch.and("states", LastHostAndStatesSearch.entity().getState(), Op.IN); LastHostAndStatesSearch.done(); + IdsPowerStateSelectSearch = createSearchBuilder(); + IdsPowerStateSelectSearch.and("id", IdsPowerStateSelectSearch.entity().getId(), Op.IN); + IdsPowerStateSelectSearch.selectFields(IdsPowerStateSelectSearch.entity().getId(), + IdsPowerStateSelectSearch.entity().getPowerHostId(), + IdsPowerStateSelectSearch.entity().getPowerState(), + IdsPowerStateSelectSearch.entity().getPowerStateUpdateCount(), + IdsPowerStateSelectSearch.entity().getPowerStateUpdateTime()); + IdsPowerStateSelectSearch.done(); + } @Override @@ -896,7 +905,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem } @Override - public List findByHostInStatesExcluding(Long hostId, Set excludingIds, State... states) { + public List findByHostInStatesExcluding(Long hostId, Collection excludingIds, State... states) { SearchCriteria sc = HostAndStateSearch.create(); sc.setParameters("host", hostId); if (excludingIds != null && !excludingIds.isEmpty()) { @@ -921,6 +930,28 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem return listBy(sc); } + protected List listSelectPowerStateByIds(final List ids) { + SearchCriteria sc = IdsPowerStateSelectSearch.create(); + sc.setParameters("id", ids.toArray()); + return customSearch(sc, null); + } + + protected Integer getPowerUpdateCount(final VMInstanceVO instance, final long powerHostId, final VirtualMachine.PowerState powerState, Date wisdomEra) { + if (instance.getPowerStateUpdateTime() == null || instance.getPowerStateUpdateTime().before(wisdomEra)) { + Long savedPowerHostId = instance.getPowerHostId(); + boolean isStateMismatch = instance.getPowerState() != powerState + || savedPowerHostId == null + || !savedPowerHostId.equals(powerHostId) + || !isPowerStateInSyncWithInstanceState(powerState, powerHostId, instance); + if (isStateMismatch) { + return 1; + } else if (instance.getPowerStateUpdateCount() < MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT) { + return instance.getPowerStateUpdateCount() + 1; + } + } + return null; + } + @Override public boolean updatePowerState(final long instanceId, final long powerHostId, final VirtualMachine.PowerState powerState, Date wisdomEra) { return Transaction.execute((TransactionCallback) status -> { @@ -954,6 +985,49 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem }); } + @Override + public Map updatePowerState(Map instancePowerStates, long powerHostId, Date wisdomEra) { + Map notUpdated = new HashMap<>(); + List instances = listSelectPowerStateByIds(new ArrayList<>(instancePowerStates.keySet())); + Map updateCounts = new HashMap<>(); + for (VMInstanceVO instance : instances) { + VirtualMachine.PowerState powerState = instancePowerStates.get(instance.getId()); + Integer count = getPowerUpdateCount(instance, powerHostId, powerState, wisdomEra); + if (count != null) { + updateCounts.put(instance.getId(), count); + } else { + notUpdated.put(instance.getId(), powerState); + } + } + if (updateCounts.isEmpty()) { + return notUpdated; + } + StringBuilder sql = new StringBuilder("UPDATE vm_instance SET " + + "power_host = ?, power_state_update_time = now(), power_state = CASE "); + updateCounts.keySet().forEach(key -> { + sql.append("WHEN id = ").append(key).append(" THEN '").append(instancePowerStates.get(key)).append("' "); + }); + sql.append("END, power_state_update_count = CASE "); + StringBuilder idList = new StringBuilder(); + updateCounts.forEach((key, value) -> { + sql.append("WHEN id = ").append(key).append(" THEN ").append(value).append(" "); + idList.append(key).append(","); + }); + idList.setLength(idList.length() - 1); + sql.append("END WHERE id IN (").append(idList).append(")"); + try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB)) { + try (PreparedStatement pstmt = txn.prepareAutoCloseStatement(sql.toString())) { + pstmt.setLong(1, powerHostId); + pstmt.executeUpdate(); + } catch (SQLException e) { + s_logger.error(String.format("Unable to execute update power states SQL from VMs %s due to: %s", + idList, e.getMessage()), e); + return instancePowerStates; + } + } + return notUpdated; + } + private boolean isPowerStateInSyncWithInstanceState(final VirtualMachine.PowerState powerState, final long powerHostId, final VMInstanceVO instance) { State instanceState = instance.getState(); if ((powerState == VirtualMachine.PowerState.PowerOff && instanceState == State.Running) @@ -966,11 +1040,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem } @Override - public boolean isPowerStateUpToDate(final long instanceId) { - VMInstanceVO instance = findById(instanceId); - if(instance == null) { - throw new CloudRuntimeException("checking power state update count on non existing instance " + instanceId); - } + public boolean isPowerStateUpToDate(final VMInstanceVO instance) { return instance.getPowerStateUpdateCount() < MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT; } @@ -989,6 +1059,22 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem }); } + @Override + public void resetVmPowerStateTracking(List instanceIds) { + Transaction.execute(new TransactionCallbackNoReturn() { + @Override + public void doInTransactionWithoutResult(TransactionStatus status) { + SearchCriteria sc = IdsPowerStateSelectSearch.create(); + sc.setParameters("id", instanceIds.toArray()); + VMInstanceVO vm = createForUpdate(); + vm.setPowerStateUpdateCount(0); + vm.setPowerStateUpdateTime(DateUtil.currentGMTTime()); + UpdateBuilder ub = getUpdateBuilder(vm); + update(ub, sc, null); + } + }); + } + @Override @DB public void resetHostPowerStateTracking(final long hostId) { Transaction.execute(new TransactionCallbackNoReturn() { From 56d8ae371c12b2a17646379349d0874cf3be9946 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 7 Oct 2024 16:36:03 +0530 Subject: [PATCH 45/62] minor test revert Signed-off-by: Abhishek Kumar --- utils/src/test/java/com/cloud/utils/testcase/NioTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java index d8d6adde747..c79bf7c08ce 100644 --- a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java +++ b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java @@ -98,7 +98,7 @@ public class NioTest { testBytes = new byte[1000000]; randomGenerator.nextBytes(testBytes); - server = new NioServer("NioTestServer", 0, 10, 1, 2 * totalTestCount, new NioTestServer(), null, null); + server = new NioServer("NioTestServer", 0, 1, 1, 2 * totalTestCount, new NioTestServer(), null, null); try { server.start(); } catch (final NioConnectionException e) { From 3fa9334954b66970e99aa2b8edd6c332d0572f08 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 7 Oct 2024 17:30:56 +0530 Subject: [PATCH 46/62] limits changes for listing accounts and domains Signed-off-by: Abhishek Kumar --- .../api/command/admin/domain/ListDomainsCmd.java | 7 +++++-- .../api/command/user/account/ListAccountsCmd.java | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java index d4e763b4f9c..598d8789bcb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java @@ -103,7 +103,7 @@ public class ListDomainsCmd extends BaseListCmd implements UserCmd { dv = EnumSet.of(DomainDetails.all); } else { try { - ArrayList dc = new ArrayList(); + ArrayList dc = new ArrayList<>(); for (String detail : viewDetails) { dc.add(DomainDetails.valueOf(detail)); } @@ -145,7 +145,10 @@ public class ListDomainsCmd extends BaseListCmd implements UserCmd { if (CollectionUtils.isEmpty(response)) { return; } - _resourceLimitService.updateTaggedResourceLimitsAndCountsForDomains(response, getTag()); + EnumSet details = getDetails(); + if (details.contains(DomainDetails.all) || details.contains(DomainDetails.resource)) { + _resourceLimitService.updateTaggedResourceLimitsAndCountsForDomains(response, getTag()); + } if (!getShowIcon()) { return; } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java index d04d52ab09f..6617442f282 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java @@ -151,7 +151,10 @@ public class ListAccountsCmd extends BaseListDomainResourcesCmd implements UserC if (CollectionUtils.isEmpty(response)) { return; } - _resourceLimitService.updateTaggedResourceLimitsAndCountsForAccounts(response, getTag()); + EnumSet details = getDetails(); + if (details.contains(DomainDetails.all) || details.contains(DomainDetails.resource)) { + _resourceLimitService.updateTaggedResourceLimitsAndCountsForAccounts(response, getTag()); + } if (!getShowIcon()) { return; } From c6cc136ce6e081c99f89b7e8f46e428626b9afbc Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 8 Oct 2024 14:24:09 +0530 Subject: [PATCH 47/62] changes in pools for agent executors Signed-off-by: Abhishek Kumar --- .../com/cloud/agent/manager/AgentManagerImpl.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java index eb77f2944a5..a99a6aaddf1 100644 --- a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java @@ -180,7 +180,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl protected ExecutorService _executor; protected ThreadPoolExecutor _connectExecutor; - protected ScheduledExecutorService _directAgentExecutor; + protected ThreadPoolExecutor _directAgentExecutor; protected ScheduledExecutorService _cronJobExecutor; protected ScheduledExecutorService _monitorExecutor; @@ -222,8 +222,6 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl s_logger.info("Ping Timeout is " + mgmtServiceConf.getPingTimeout()); - final int threads = DirectAgentLoadSize.value(); - _nodeId = ManagementServerNode.getManagementServerId(); s_logger.info("Configuring AgentManagerImpl. management server node id(msid): " + _nodeId); @@ -234,7 +232,8 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl registerForHostEvents(new SetHostParamsListener(), true, true, false); - _executor = new ThreadPoolExecutor(threads, threads, 60l, TimeUnit.SECONDS, new LinkedBlockingQueue(), new NamedThreadFactory("AgentTaskPool")); + final int agentTaskThreads = DirectAgentLoadSize.value(); + _executor = new ThreadPoolExecutor(Math.max(agentTaskThreads/10, 1), agentTaskThreads, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue(), new NamedThreadFactory("AgentTaskPool")); _connectExecutor = new ThreadPoolExecutor(100, 500, 60l, TimeUnit.SECONDS, new LinkedBlockingQueue(), new NamedThreadFactory("AgentConnectTaskPool")); // allow core threads to time out even when there are no items in the queue @@ -246,7 +245,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl s_logger.info("Listening on " + Port.value() + " with " + Workers.value() + " workers"); // executes all agent commands other than cron and ping - _directAgentExecutor = new ScheduledThreadPoolExecutor(DirectAgentPoolSize.value(), new NamedThreadFactory("DirectAgent")); + _directAgentExecutor = new ThreadPoolExecutor(Math.max(agentTaskThreads/10, 1), DirectAgentPoolSize.value(), 120L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("DirectAgent")); // executes cron and ping agent commands _cronJobExecutor = new ScheduledThreadPoolExecutor(DirectAgentPoolSize.value(), new NamedThreadFactory("DirectAgentCronJob")); s_logger.debug("Created DirectAgentAttache pool with size: " + DirectAgentPoolSize.value()); @@ -1678,7 +1677,7 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl } } - public ScheduledExecutorService getDirectAgentPool() { + public ThreadPoolExecutor getDirectAgentPool() { return _directAgentExecutor; } From a069e14cf9df3e38252f462d3946de1ea901f131 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 8 Oct 2024 14:25:25 +0530 Subject: [PATCH 48/62] directly return count for systemvms used in listInfra Signed-off-by: Abhishek Kumar --- .../schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java | 2 +- .../src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java | 4 ++-- .../org/apache/cloudstack/metrics/MetricsServiceImpl.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java index a92ecabef83..77e3c95b648 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java @@ -82,7 +82,7 @@ public interface VMInstanceDao extends GenericDao, StateDao< List listByHostAndState(long hostId, State... states); - List listByTypes(VirtualMachine.Type... types); + int countByTypes(VirtualMachine.Type... types); VMInstanceVO findByIdTypes(long id, VirtualMachine.Type... types); diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java index 79f11e6fb4e..3e989362f84 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -466,10 +466,10 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem } @Override - public List listByTypes(Type... types) { + public int countByTypes(Type... types) { SearchCriteria sc = TypesSearch.create(); sc.setParameters("types", (Object[])types); - return listBy(sc); + return getCount(sc); } @Override diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java index 2bed94c8dea..ca37e4b2e36 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java @@ -558,7 +558,7 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements response.setHosts(hostDao.countAllByType(Host.Type.Routing)); response.setStoragePools(storagePoolDao.countAll()); response.setImageStores(imageStoreDao.countAllImageStores()); - response.setSystemvms(vmInstanceDao.listByTypes(VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm).size()); + response.setSystemvms(vmInstanceDao.countByTypes(VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm)); response.setRouters(domainRouterDao.countAllByRole(VirtualRouter.Role.VIRTUAL_ROUTER)); response.setInternalLbs(domainRouterDao.countAllByRole(VirtualRouter.Role.INTERNAL_LB_VM)); response.setAlerts(alertDao.countAll()); From 3f6b7b930aa7d541cbed408aad75a864e1ef2a0c Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 8 Oct 2024 14:27:26 +0530 Subject: [PATCH 49/62] during resourcecalculation select specific fields for uservmjoinvo Signed-off-by: Abhishek Kumar --- .../src/main/java/com/cloud/api/query/dao/UserVmJoinDao.java | 4 ++-- .../main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDao.java b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDao.java index 2f3fc742383..9cf487657fd 100644 --- a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDao.java +++ b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDao.java @@ -42,6 +42,6 @@ public interface UserVmJoinDao extends GenericDao { List listActiveByIsoId(Long isoId); - List listByAccountServiceOfferingTemplateAndNotInState(long accountId, List states, - List offeringIds, List templateIds); + List listByAccountServiceOfferingTemplateAndNotInState(long accountId, + List states, List offeringIds, List templateIds); } diff --git a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java index d0d4927f543..e6f7392a7dc 100644 --- a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java @@ -624,6 +624,8 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation listByAccountServiceOfferingTemplateAndNotInState(long accountId, List states, List offeringIds, List templateIds) { SearchBuilder userVmSearch = createSearchBuilder(); + userVmSearch.selectFields(userVmSearch.entity().getId(), userVmSearch.entity().getCpu(), + userVmSearch.entity().getRamSize()); userVmSearch.and("accountId", userVmSearch.entity().getAccountId(), Op.EQ); userVmSearch.and("serviceOfferingId", userVmSearch.entity().getServiceOfferingId(), Op.IN); userVmSearch.and("templateId", userVmSearch.entity().getTemplateId(), Op.IN); @@ -644,6 +646,6 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation Date: Tue, 8 Oct 2024 14:28:26 +0530 Subject: [PATCH 50/62] during resource calculation directly return ids for service offering, templates Signed-off-by: Abhishek Kumar --- .../com/cloud/service/dao/ServiceOfferingDao.java | 2 +- .../cloud/service/dao/ServiceOfferingDaoImpl.java | 11 +++++++---- .../java/com/cloud/storage/dao/VMTemplateDao.java | 2 +- .../com/cloud/storage/dao/VMTemplateDaoImpl.java | 9 +++++---- .../resourcelimit/ResourceLimitManagerImpl.java | 11 ++++------- .../ResourceLimitManagerImplTest.java | 14 ++++---------- 6 files changed, 22 insertions(+), 27 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java index d086ad1dac1..584dd58e494 100644 --- a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java +++ b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java @@ -56,5 +56,5 @@ public interface ServiceOfferingDao extends GenericDao ServiceOfferingVO findServiceOfferingByComputeOnlyDiskOffering(long diskOfferingId); - List listByHostTag(String tag); + List listIdsByHostTag(String tag); } diff --git a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java index e03aaa1c390..fcdb39deed9 100644 --- a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java @@ -35,6 +35,7 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.Storage.ProvisioningType; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.exception.CloudRuntimeException; @@ -295,8 +296,9 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase listByHostTag(String tag) { - SearchBuilder sb = createSearchBuilder(); + public List listIdsByHostTag(String tag) { + GenericSearchBuilder sb = createSearchBuilder(Long.class); + sb.selectFields(sb.entity().getId()); sb.and("tagNotNull", sb.entity().getHostTag(), SearchCriteria.Op.NNULL); sb.and().op("tagEq", sb.entity().getHostTag(), SearchCriteria.Op.EQ); sb.or("tagStartLike", sb.entity().getHostTag(), SearchCriteria.Op.LIKE); @@ -304,11 +306,12 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase sc = sb.create(); + SearchCriteria sc = sb.create(); + sc.setParameters("tagEq", tag); sc.setParameters("tagStartLike", tag + ",%"); sc.setParameters("tagMidLike", "%," + tag + ",%"); sc.setParameters("tagEndLike", "%," + tag); - return listBy(sc); + return customSearch(sc, null); } } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java index f1b01d12b64..c6956e6f34b 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java @@ -91,5 +91,5 @@ public interface VMTemplateDao extends GenericDao, StateDao< List findTemplatesLinkedToUserdata(long userdataId); - List listByTemplateTag(String tag); + List listIdsByTemplateTag(String tag); } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java index dd5bc19df5c..6cb32925d5b 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -672,13 +672,14 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem } @Override - public List listByTemplateTag(String tag) { - SearchBuilder sb = createSearchBuilder(); + public List listIdsByTemplateTag(String tag) { + GenericSearchBuilder sb = createSearchBuilder(Long.class); + sb.selectFields(sb.entity().getId()); sb.and("tag", sb.entity().getTemplateTag(), SearchCriteria.Op.EQ); sb.done(); - SearchCriteria sc = sb.create(); + SearchCriteria sc = sb.create(); sc.setParameters("tag", tag); - return listIncludingRemovedBy(sc); + return customSearchIncludingRemoved(sc, null); } @Override diff --git a/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index c6e2bf90d75..a97b48bea1d 100644 --- a/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -94,7 +94,6 @@ import com.cloud.projects.Project; import com.cloud.projects.ProjectAccount.Role; import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.projects.dao.ProjectDao; -import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DataStoreRole; import com.cloud.storage.DiskOfferingVO; @@ -1294,16 +1293,14 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim if (StringUtils.isEmpty(tag)) { return _userVmJoinDao.listByAccountServiceOfferingTemplateAndNotInState(accountId, states, null, null); } - List offerings = serviceOfferingDao.listByHostTag(tag); - List templates = _vmTemplateDao.listByTemplateTag(tag); + List offerings = serviceOfferingDao.listIdsByHostTag(tag); + List templates = _vmTemplateDao.listIdsByTemplateTag(tag); if (CollectionUtils.isEmpty(offerings) && CollectionUtils.isEmpty(templates)) { return new ArrayList<>(); } return _userVmJoinDao.listByAccountServiceOfferingTemplateAndNotInState(accountId, states, - offerings.stream().map(ServiceOfferingVO::getId).collect(Collectors.toList()), - templates.stream().map(VMTemplateVO::getId).collect(Collectors.toList()) - ); + offerings, templates); } protected List getVmsWithAccount(long accountId) { @@ -1321,7 +1318,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim vrIds); } - private long calculateReservedResources(List vms,long accountId, ResourceType type, String tag) { + private long calculateReservedResources(List vms, long accountId, ResourceType type, String tag) { Set vmIds = vms.stream().map(UserVmJoinVO::getId).collect(Collectors.toSet()); List reservations = reservationDao.getReservationsForAccount(accountId, type, tag); long reserved = 0; diff --git a/server/src/test/java/com/cloud/resourcelimit/ResourceLimitManagerImplTest.java b/server/src/test/java/com/cloud/resourcelimit/ResourceLimitManagerImplTest.java index 5074a7cbe47..456dc1cea55 100644 --- a/server/src/test/java/com/cloud/resourcelimit/ResourceLimitManagerImplTest.java +++ b/server/src/test/java/com/cloud/resourcelimit/ResourceLimitManagerImplTest.java @@ -58,10 +58,8 @@ import com.cloud.offering.DiskOffering; import com.cloud.offering.ServiceOffering; import com.cloud.projects.ProjectVO; import com.cloud.projects.dao.ProjectDao; -import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; -import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.VMTemplateDao; @@ -614,8 +612,8 @@ public class ResourceLimitManagerImplTest { @Test public void testGetVmsWithAccountAndTagNegative() { String tag = hostTags.get(0); - Mockito.when(serviceOfferingDao.listByHostTag(tag)).thenReturn(null); - Mockito.when(vmTemplateDao.listByTemplateTag(tag)).thenReturn(null); + Mockito.when(serviceOfferingDao.listIdsByHostTag(tag)).thenReturn(null); + Mockito.when(vmTemplateDao.listIdsByTemplateTag(tag)).thenReturn(null); List result = resourceLimitManager.getVmsWithAccountAndTag(1L, hostTags.get(0)); Assert.assertTrue(CollectionUtils.isEmpty(result)); } @@ -624,12 +622,8 @@ public class ResourceLimitManagerImplTest { public void testGetVmsWithAccountAndTag() throws NoSuchFieldException, IllegalAccessException { overrideDefaultConfigValue(VirtualMachineManager.ResourceCountRunningVMsonly, "_defaultValue", "true"); String tag = hostTags.get(0); - ServiceOfferingVO serviceOfferingVO = Mockito.mock(ServiceOfferingVO.class); - Mockito.when(serviceOfferingVO.getId()).thenReturn(1L); - VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class); - Mockito.when(templateVO.getId()).thenReturn(1L); - Mockito.when(serviceOfferingDao.listByHostTag(tag)).thenReturn(List.of(serviceOfferingVO)); - Mockito.when(vmTemplateDao.listByTemplateTag(tag)).thenReturn(List.of(templateVO)); + Mockito.when(serviceOfferingDao.listIdsByHostTag(tag)).thenReturn(List.of(1L)); + Mockito.when(vmTemplateDao.listIdsByTemplateTag(tag)).thenReturn(List.of(1L)); List vmList = List.of(Mockito.mock(UserVmJoinVO.class)); Mockito.when(userVmJoinDao.listByAccountServiceOfferingTemplateAndNotInState(Mockito.anyLong(), Mockito.anyList(), Mockito.anyList(), Mockito.anyList())).thenReturn(vmList); List result = resourceLimitManager.getVmsWithAccountAndTag(1L, tag); From f85ac6adf90bfc5853a0e9a2b5b99225d9909550 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 8 Oct 2024 14:30:45 +0530 Subject: [PATCH 51/62] add a todo Signed-off-by: Abhishek Kumar --- server/src/main/java/com/cloud/api/query/dao/UserVmJoinDao.java | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDao.java b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDao.java index 9cf487657fd..eb166dcdf66 100644 --- a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDao.java +++ b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDao.java @@ -42,6 +42,7 @@ public interface UserVmJoinDao extends GenericDao { List listActiveByIsoId(Long isoId); + // TODO - We only need id, cpu and ram_size here. This could be done using JOIN on fly List listByAccountServiceOfferingTemplateAndNotInState(long accountId, List states, List offeringIds, List templateIds); } From 864afda9351e3791ec094579028cc0b03379bf73 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 8 Oct 2024 16:03:31 +0530 Subject: [PATCH 52/62] backoff changes Signed-off-by: Abhishek Kumar --- .../backoff/impl/ConstantTimeBackoff.java | 1 - .../utils/backoff/impl/RangeTimeBackoff.java | 8 +-- .../backoff/impl/RangeTimeBackoffTest.java | 70 +++++++++++++++++++ 3 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java diff --git a/utils/src/main/java/com/cloud/utils/backoff/impl/ConstantTimeBackoff.java b/utils/src/main/java/com/cloud/utils/backoff/impl/ConstantTimeBackoff.java index c48f4462a52..de8f221e1e1 100644 --- a/utils/src/main/java/com/cloud/utils/backoff/impl/ConstantTimeBackoff.java +++ b/utils/src/main/java/com/cloud/utils/backoff/impl/ConstantTimeBackoff.java @@ -56,7 +56,6 @@ public class ConstantTimeBackoff extends AdapterBase implements BackoffAlgorithm } finally { _asleep.remove(current.getName()); } - return; } @Override diff --git a/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java b/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java index 8104caa69c6..9f7d1fbc8c0 100644 --- a/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java +++ b/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java @@ -36,7 +36,7 @@ import com.cloud.utils.component.AdapterBase; * **/ public class RangeTimeBackoff extends AdapterBase implements BackoffAlgorithm { - private static final int DEFAULT_MIN_TIME = 5; + protected static final int DEFAULT_MIN_TIME = 5; private int minTime = DEFAULT_MIN_TIME; private int maxTime = 3 * DEFAULT_MIN_TIME; private final Map asleep = new ConcurrentHashMap<>(); @@ -44,11 +44,12 @@ public class RangeTimeBackoff extends AdapterBase implements BackoffAlgorithm { @Override public void waitBeforeRetry() { + long time = minTime * 1000L; Thread current = Thread.currentThread(); try { asleep.put(current.getName(), current); - long time = ThreadLocalRandom.current().nextInt(minTime, maxTime) * 1000L; - LOG.info("Waiting " + current.getName() + " for " + time); + time = ThreadLocalRandom.current().nextInt(minTime, maxTime) * 1000L; + LOG.debug("Waiting " + current.getName() + " for " + time); Thread.sleep(time); } catch (InterruptedException e) { // JMX or other threads may interrupt this thread, but let's log it @@ -57,7 +58,6 @@ public class RangeTimeBackoff extends AdapterBase implements BackoffAlgorithm { } finally { asleep.remove(current.getName()); } - return; } @Override diff --git a/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java b/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java new file mode 100644 index 00000000000..28241a4b85a --- /dev/null +++ b/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java @@ -0,0 +1,70 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.utils.backoff.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class RangeTimeBackoffTest { + + @Test + public void testWaitValidValue() { + RangeTimeBackoff backoff = new RangeTimeBackoff(); + Map map = new HashMap<>(); + int min = 5; + int max = 10; + map.put("minSeconds", String.valueOf(min)); + map.put("maxSeconds", String.valueOf(max)); + backoff.configure("RangeTimeBackoff", map); + long startTime = System.currentTimeMillis(); + backoff.waitBeforeRetry(); + long timeTaken = System.currentTimeMillis() - startTime; + Assert.assertTrue(timeTaken >= min * 1000L); + Assert.assertTrue(timeTaken <= max * 1000L); + } + + @Test + public void testWaitEmptyValue() { + RangeTimeBackoff backoff = new RangeTimeBackoff(); + Map map = new HashMap<>(); + map.put("minSeconds", ""); + map.put("maxSeconds", ""); + backoff.configure("RangeTimeBackoff", map); + long startTime = System.currentTimeMillis(); + backoff.waitBeforeRetry(); + long timeTaken = System.currentTimeMillis() - startTime; + Assert.assertTrue(timeTaken >= RangeTimeBackoff.DEFAULT_MIN_TIME * 1000L); + } + + @Test + public void testWaitNullValue() { + RangeTimeBackoff backoff = new RangeTimeBackoff(); + Map map = new HashMap<>(); + backoff.configure("RangeTimeBackoff", map); + long startTime = System.currentTimeMillis(); + backoff.waitBeforeRetry(); + long timeTaken = System.currentTimeMillis() - startTime; + Assert.assertTrue(timeTaken >= RangeTimeBackoff.DEFAULT_MIN_TIME * 1000L); + } + +} From 3e830252aba6d7875070735ba2d05747761c9a8c Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 8 Oct 2024 17:36:55 +0530 Subject: [PATCH 53/62] fix invalid range Signed-off-by: Abhishek Kumar --- .../utils/backoff/impl/RangeTimeBackoff.java | 10 +++++++--- .../backoff/impl/RangeTimeBackoffTest.java | 18 ++++++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java b/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java index 9f7d1fbc8c0..b4bdc47c653 100644 --- a/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java +++ b/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java @@ -44,12 +44,16 @@ public class RangeTimeBackoff extends AdapterBase implements BackoffAlgorithm { @Override public void waitBeforeRetry() { - long time = minTime * 1000L; + long time = Math.max(minTime, 0) * 1000L; Thread current = Thread.currentThread(); try { asleep.put(current.getName(), current); - time = ThreadLocalRandom.current().nextInt(minTime, maxTime) * 1000L; - LOG.debug("Waiting " + current.getName() + " for " + time); + if (maxTime > minTime) { + time = ThreadLocalRandom.current().nextInt(minTime, maxTime) * 1000L; + } + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("Waiting %s for %d milliseconds", current.getName(), time)); + } Thread.sleep(time); } catch (InterruptedException e) { // JMX or other threads may interrupt this thread, but let's log it diff --git a/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java b/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java index 28241a4b85a..01a3c950ddd 100644 --- a/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java +++ b/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java @@ -31,8 +31,8 @@ public class RangeTimeBackoffTest { public void testWaitValidValue() { RangeTimeBackoff backoff = new RangeTimeBackoff(); Map map = new HashMap<>(); - int min = 5; - int max = 10; + int min = 1; + int max = 3; map.put("minSeconds", String.valueOf(min)); map.put("maxSeconds", String.valueOf(max)); backoff.configure("RangeTimeBackoff", map); @@ -67,4 +67,18 @@ public class RangeTimeBackoffTest { Assert.assertTrue(timeTaken >= RangeTimeBackoff.DEFAULT_MIN_TIME * 1000L); } + @Test + public void testWaitVMinHigherThanMax() { + RangeTimeBackoff backoff = new RangeTimeBackoff(); + Map map = new HashMap<>(); + int min = 3; + int max = 2; + map.put("minSeconds", String.valueOf(min)); + map.put("maxSeconds", String.valueOf(max)); + backoff.configure("RangeTimeBackoff", map); + long startTime = System.currentTimeMillis(); + backoff.waitBeforeRetry(); + long timeTaken = System.currentTimeMillis() - startTime; + Assert.assertTrue(timeTaken >= min * 1000L); + } } From 1589cde4e40d4d09aabf41d521447e6ab2a6c0d6 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2024 16:27:39 +0530 Subject: [PATCH 54/62] check for empty ids Signed-off-by: Abhishek Kumar --- .../schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java | 3 +++ .../src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java index 7c412df4b78..e3f594236ab 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java @@ -1613,6 +1613,9 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao @Override public List listByIds(List ids) { + if (CollectionUtils.isEmpty(ids)) { + return new ArrayList<>(); + } SearchCriteria sc = IdsSearch.create(); sc.setParameters("id", ids.toArray()); return search(sc, null); diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java index 3e989362f84..df4160c2297 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -931,6 +931,9 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem } protected List listSelectPowerStateByIds(final List ids) { + if (CollectionUtils.isEmpty(ids)) { + return new ArrayList<>(); + } SearchCriteria sc = IdsPowerStateSelectSearch.create(); sc.setParameters("id", ids.toArray()); return customSearch(sc, null); From 5f86dad4cb098eb103cb24d839e264acee352a18 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2024 16:28:24 +0530 Subject: [PATCH 55/62] improve cluster overcommit value cache Signed-off-by: Abhishek Kumar --- .../java/com/cloud/dc/ClusterDetailsDao.java | 4 ++++ .../com/cloud/dc/ClusterDetailsDaoImpl.java | 20 +++++++++++++++++++ .../cloud/capacity/CapacityManagerImpl.java | 20 +++++++++---------- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDao.java b/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDao.java index 06c9c525504..6be8e67479f 100644 --- a/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDao.java +++ b/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDao.java @@ -16,6 +16,8 @@ // under the License. package com.cloud.dc; +import java.util.Collection; +import java.util.List; import java.util.Map; import com.cloud.utils.db.GenericDao; @@ -29,6 +31,8 @@ public interface ClusterDetailsDao extends GenericDao { ClusterDetailsVO findDetail(long clusterId, String name); + Map findDetails(long clusterId, Collection names); + void deleteDetails(long clusterId); String getVmwareDcName(Long clusterId); diff --git a/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDaoImpl.java b/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDaoImpl.java index 0e40f8475c1..a4f6acb9057 100644 --- a/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDaoImpl.java @@ -16,13 +16,16 @@ // under the License. package com.cloud.dc; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.ConfigKey.Scope; import org.apache.cloudstack.framework.config.ScopedConfigStorage; +import org.apache.commons.collections.CollectionUtils; import com.cloud.utils.crypt.DBEncryptionUtil; import com.cloud.utils.db.GenericDaoBase; @@ -82,6 +85,23 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase findDetails(long clusterId, Collection names) { + if (CollectionUtils.isEmpty(names)) { + return new HashMap<>(); + } + SearchBuilder sb = createSearchBuilder(); + sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.IN); + sb.done(); + SearchCriteria sc = sb.create(); + sc.setParameters("clusterId", clusterId); + sc.setParameters("name", names.toArray()); + List results = search(sc, null); + return results.stream() + .collect(Collectors.toMap(ClusterDetailsVO::getName, ClusterDetailsVO::getValue)); + } + @Override public void deleteDetails(long clusterId) { SearchCriteria sc = ClusterSearch.create(); diff --git a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java index a35fd5f5889..d87dcab1ac4 100644 --- a/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/main/java/com/cloud/capacity/CapacityManagerImpl.java @@ -148,7 +148,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, @Inject MessageBus _messageBus; - private LazyCache> clusterValuesCache; + private LazyCache> clusterValuesCache; private SingleCache> serviceOfferingsCache; private QueuedExecutor hostCapacityUpdateExecutor; @@ -170,7 +170,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, public boolean start() { _resourceMgr.registerResourceEvent(ResourceListener.EVENT_PREPARE_MAINTENANCE_AFTER, this); _resourceMgr.registerResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, this); - clusterValuesCache = new LazyCache<>(16, 60, this::getClusterValues); + clusterValuesCache = new LazyCache<>(128, 60, this::getClusterValues); serviceOfferingsCache = new SingleCache<>(60, this::getServiceOfferingsMap); hostCapacityUpdateExecutor.startProcessing(); return true; @@ -652,9 +652,11 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, hostCapacityUpdateExecutor.queueRequest(host); } - protected Pair getClusterValues(long clusterId) { - return new Pair<>(_clusterDetailsDao.findDetail(clusterId, VmDetailConstants.CPU_OVER_COMMIT_RATIO), - _clusterDetailsDao.findDetail(clusterId, VmDetailConstants.MEMORY_OVER_COMMIT_RATIO)); + protected Pair getClusterValues(long clusterId) { + Map map = _clusterDetailsDao.findDetails(clusterId, + List.of(VmDetailConstants.CPU_OVER_COMMIT_RATIO, VmDetailConstants.CPU_OVER_COMMIT_RATIO)); + return new Pair<>(map.get(VmDetailConstants.CPU_OVER_COMMIT_RATIO), + map.get(VmDetailConstants.CPU_OVER_COMMIT_RATIO)); } @@ -712,12 +714,10 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, } vms.addAll(vosMigrating); - Pair clusterValues = + Pair clusterValues = clusterValuesCache.get(host.getClusterId()); - ClusterDetailsVO clusterDetailCpu = clusterValues.first(); - ClusterDetailsVO clusterDetailRam = clusterValues.second(); - Float clusterCpuOvercommitRatio = Float.parseFloat(clusterDetailCpu.getValue()); - Float clusterRamOvercommitRatio = Float.parseFloat(clusterDetailRam.getValue()); + Float clusterCpuOvercommitRatio = Float.parseFloat(clusterValues.first()); + Float clusterRamOvercommitRatio = Float.parseFloat(clusterValues.second()); for (VMInstanceVO vm : vms) { Float cpuOvercommitRatio = 1.0f; Float ramOvercommitRatio = 1.0f; From 0b8ebb08d6651292f93ffdaba8f54f6b1f1f1d8b Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2024 17:18:44 +0530 Subject: [PATCH 56/62] increase expiry Signed-off-by: Abhishek Kumar --- .../hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java index 3b30c2749a6..18d086eccfa 100644 --- a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java +++ b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java @@ -435,7 +435,7 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements _kvmGuestNic = _kvmPrivateNic; } - clusterExistingHostCache = new LazyCache<>(32, 15, + clusterExistingHostCache = new LazyCache<>(32, 30, this::getExistingHostForCluster); agentMgr.registerForHostEvents(this, true, false, false); From 3ebc6c3d1eefdabe1b7baf401fc9e660ec3737bc Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2024 17:19:18 +0530 Subject: [PATCH 57/62] agent ssl handshake timeout Signed-off-by: Abhishek Kumar --- agent/src/main/java/com/cloud/agent/Agent.java | 8 ++++---- agent/src/main/java/com/cloud/agent/AgentShell.java | 5 +++++ agent/src/main/java/com/cloud/agent/IAgentShell.java | 2 ++ .../java/com/cloud/agent/properties/AgentProperties.java | 7 +++++++ utils/src/main/java/com/cloud/utils/nio/NioClient.java | 2 +- utils/src/test/java/com/cloud/utils/testcase/NioTest.java | 4 ++-- 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/agent/src/main/java/com/cloud/agent/Agent.java b/agent/src/main/java/com/cloud/agent/Agent.java index 9e0ee746c03..83187c3b60d 100644 --- a/agent/src/main/java/com/cloud/agent/Agent.java +++ b/agent/src/main/java/com/cloud/agent/Agent.java @@ -159,7 +159,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater _shell = shell; _link = null; - _connection = new NioClient("Agent", _shell.getNextHost(), _shell.getPort(), _shell.getWorkers(), this); + _connection = new NioClient("Agent", _shell.getNextHost(), _shell.getPort(), _shell.getWorkers(), _shell.getSslHandshakeTimeout(), this); Runtime.getRuntime().addShutdownHook(_shutdownThread); @@ -195,7 +195,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater } final String host = _shell.getNextHost(); - _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this); + _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), _shell.getSslHandshakeTimeout(), this); // ((NioClient)_connection).setBindAddress(_shell.getPrivateIp()); @@ -291,7 +291,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater while (!_connection.isStartup()) { final String host = _shell.getNextHost(); _shell.getBackoffAlgorithm().waitBeforeRetry(); - _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this); + _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), _shell.getSslHandshakeTimeout(), this); s_logger.info("Connecting to host:" + host); try { _connection.start(); @@ -552,7 +552,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater do { final String host = _shell.getNextHost(); - _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this); + _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), _shell.getSslHandshakeTimeout(), this); s_logger.info("Reconnecting to host:" + host); try { _connection.start(); diff --git a/agent/src/main/java/com/cloud/agent/AgentShell.java b/agent/src/main/java/com/cloud/agent/AgentShell.java index faa2322d8b6..ff265e01921 100644 --- a/agent/src/main/java/com/cloud/agent/AgentShell.java +++ b/agent/src/main/java/com/cloud/agent/AgentShell.java @@ -459,6 +459,11 @@ public class AgentShell implements IAgentShell, Daemon { agent.start(); } + @Override + public Integer getSslHandshakeTimeout() { + return AgentPropertiesFileHandler.getPropertyValue(AgentProperties.SSL_HANDSHAKE_TIMEOUT); + } + public synchronized int getNextAgentId() { return _nextAgentId++; } diff --git a/agent/src/main/java/com/cloud/agent/IAgentShell.java b/agent/src/main/java/com/cloud/agent/IAgentShell.java index 2dd08fffd45..7f04048795d 100644 --- a/agent/src/main/java/com/cloud/agent/IAgentShell.java +++ b/agent/src/main/java/com/cloud/agent/IAgentShell.java @@ -70,4 +70,6 @@ public interface IAgentShell { String getConnectedHost(); void launchNewAgent(ServerResource resource) throws ConfigurationException; + + Integer getSslHandshakeTimeout(); } diff --git a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java index 9217aaa2078..82e554d464e 100644 --- a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java +++ b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java @@ -762,6 +762,13 @@ public class AgentProperties{ */ public static final Property HOST_TAGS = new Property<>("host.tags", null, String.class); + /** + * Timeout for SSL handshake in seconds + * Data type: Integer.
+ * Default value: null + */ + public static final Property SSL_HANDSHAKE_TIMEOUT = new Property<>("ssl.handshake.timeout", null, Integer.class); + public static class Property { private String name; private T defaultValue; diff --git a/utils/src/main/java/com/cloud/utils/nio/NioClient.java b/utils/src/main/java/com/cloud/utils/nio/NioClient.java index a2e76e1d224..e5ce6836830 100644 --- a/utils/src/main/java/com/cloud/utils/nio/NioClient.java +++ b/utils/src/main/java/com/cloud/utils/nio/NioClient.java @@ -38,7 +38,7 @@ public class NioClient extends NioConnection { protected String _host; protected SocketChannel _clientConnection; - public NioClient(final String name, final String host, final int port, final int workers, final HandlerFactory factory) { + public NioClient(final String name, final String host, final int port, final int workers, final Integer sslHandshakeTimeout, final HandlerFactory factory) { super(name, port, workers, 1, 2, factory); _host = host; } diff --git a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java index c79bf7c08ce..446158b2018 100644 --- a/utils/src/test/java/com/cloud/utils/testcase/NioTest.java +++ b/utils/src/test/java/com/cloud/utils/testcase/NioTest.java @@ -110,7 +110,7 @@ public class NioTest { maliciousClients.add(maliciousClient); maliciousExecutor.submit(new ThreadedNioClient(maliciousClient)); - final NioClient client = new NioClient("NioTestClient-" + i, "127.0.0.1", server.getPort(), 1, new NioTestClient()); + final NioClient client = new NioClient("NioTestClient-" + i, "127.0.0.1", server.getPort(), 1, null, new NioTestClient()); clients.add(client); clientExecutor.submit(new ThreadedNioClient(client)); } @@ -179,7 +179,7 @@ public class NioTest { public class NioMaliciousClient extends NioClient { public NioMaliciousClient(String name, String host, int port, int workers, HandlerFactory factory) { - super(name, host, port, workers, factory); + super(name, host, port, workers, null, factory); } @Override From d0fc91ab2a652b8a18e3ff08df42627f949f5c44 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2024 17:29:18 +0530 Subject: [PATCH 58/62] build fix Signed-off-by: Abhishek Kumar --- engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDao.java | 1 - 1 file changed, 1 deletion(-) diff --git a/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDao.java b/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDao.java index 6be8e67479f..5daab544b21 100644 --- a/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDao.java +++ b/engine/schema/src/main/java/com/cloud/dc/ClusterDetailsDao.java @@ -17,7 +17,6 @@ package com.cloud.dc; import java.util.Collection; -import java.util.List; import java.util.Map; import com.cloud.utils.db.GenericDao; From 7ecc173187f360a9d729093ecb2f97fc80329497 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 11 Oct 2024 12:12:57 +0530 Subject: [PATCH 59/62] changes Signed-off-by: Abhishek Kumar --- .../utils/backoff/impl/RangeTimeBackoff.java | 4 ++-- .../utils/backoff/impl/RangeTimeBackoffTest.java | 15 +++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java b/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java index b4bdc47c653..8061c909824 100644 --- a/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java +++ b/utils/src/main/java/com/cloud/utils/backoff/impl/RangeTimeBackoff.java @@ -38,7 +38,7 @@ import com.cloud.utils.component.AdapterBase; public class RangeTimeBackoff extends AdapterBase implements BackoffAlgorithm { protected static final int DEFAULT_MIN_TIME = 5; private int minTime = DEFAULT_MIN_TIME; - private int maxTime = 3 * DEFAULT_MIN_TIME; + private int maxTime = DEFAULT_MIN_TIME; private final Map asleep = new ConcurrentHashMap<>(); private static final Logger LOG = Logger.getLogger(RangeTimeBackoff.class.getName()); @@ -71,7 +71,7 @@ public class RangeTimeBackoff extends AdapterBase implements BackoffAlgorithm { @Override public boolean configure(String name, Map params) { minTime = NumbersUtil.parseInt((String)params.get("minSeconds"), DEFAULT_MIN_TIME); - maxTime = NumbersUtil.parseInt((String)params.get("maxSeconds"), minTime * 3); + maxTime = NumbersUtil.parseInt((String)params.get("maxSeconds"), minTime); return true; } } diff --git a/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java b/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java index 01a3c950ddd..668417c5f3f 100644 --- a/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java +++ b/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java @@ -43,6 +43,12 @@ public class RangeTimeBackoffTest { Assert.assertTrue(timeTaken <= max * 1000L); } + private void checkTimeTakenBetweenDelta(long timeTaken, int value) { + long min = (value * 1000L) - 10L; + long max = (value* 1000L) + 10L; + Assert.assertTrue(min <= timeTaken && timeTaken <= max); + } + @Test public void testWaitEmptyValue() { RangeTimeBackoff backoff = new RangeTimeBackoff(); @@ -52,8 +58,7 @@ public class RangeTimeBackoffTest { backoff.configure("RangeTimeBackoff", map); long startTime = System.currentTimeMillis(); backoff.waitBeforeRetry(); - long timeTaken = System.currentTimeMillis() - startTime; - Assert.assertTrue(timeTaken >= RangeTimeBackoff.DEFAULT_MIN_TIME * 1000L); + checkTimeTakenBetweenDelta(System.currentTimeMillis() - startTime, RangeTimeBackoff.DEFAULT_MIN_TIME); } @Test @@ -63,8 +68,7 @@ public class RangeTimeBackoffTest { backoff.configure("RangeTimeBackoff", map); long startTime = System.currentTimeMillis(); backoff.waitBeforeRetry(); - long timeTaken = System.currentTimeMillis() - startTime; - Assert.assertTrue(timeTaken >= RangeTimeBackoff.DEFAULT_MIN_TIME * 1000L); + checkTimeTakenBetweenDelta(System.currentTimeMillis() - startTime, RangeTimeBackoff.DEFAULT_MIN_TIME); } @Test @@ -78,7 +82,6 @@ public class RangeTimeBackoffTest { backoff.configure("RangeTimeBackoff", map); long startTime = System.currentTimeMillis(); backoff.waitBeforeRetry(); - long timeTaken = System.currentTimeMillis() - startTime; - Assert.assertTrue(timeTaken >= min * 1000L); + checkTimeTakenBetweenDelta(System.currentTimeMillis() - startTime, min); } } From 52c483d91deae078d3a095797e62cb7b4d0eba41 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 11 Oct 2024 12:19:50 +0530 Subject: [PATCH 60/62] revert to constant backoff Signed-off-by: Abhishek Kumar --- agent/conf/agent.properties | 6 ++ .../main/java/com/cloud/agent/AgentShell.java | 11 ++- .../backoff/impl/RangeTimeBackoffTest.java | 87 ------------------- 3 files changed, 11 insertions(+), 93 deletions(-) delete mode 100644 utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties index 188007bfef2..ac98de0df8f 100644 --- a/agent/conf/agent.properties +++ b/agent/conf/agent.properties @@ -418,3 +418,9 @@ iscsi.session.cleanup.enabled=false # Implicit host tags managed by agent.properties # host.tags= + +# Timeout(in seconds) for SSL handshake when agent connects to server +#ssl.handshake.timeout= + +# Wait(in seconds) during agent reconnections +#backoff.seconds= \ No newline at end of file diff --git a/agent/src/main/java/com/cloud/agent/AgentShell.java b/agent/src/main/java/com/cloud/agent/AgentShell.java index ff265e01921..22e897384e9 100644 --- a/agent/src/main/java/com/cloud/agent/AgentShell.java +++ b/agent/src/main/java/com/cloud/agent/AgentShell.java @@ -51,7 +51,7 @@ import com.cloud.utils.LogUtils; import com.cloud.utils.ProcessUtil; import com.cloud.utils.PropertiesUtil; import com.cloud.utils.backoff.BackoffAlgorithm; -import com.cloud.utils.backoff.impl.RangeTimeBackoff; +import com.cloud.utils.backoff.impl.ConstantTimeBackoff; import com.cloud.utils.exception.CloudRuntimeException; public class AgentShell implements IAgentShell, Daemon { @@ -405,12 +405,11 @@ public class AgentShell implements IAgentShell, Daemon { _properties.put(cmdLineProp.getKey(), cmdLineProp.getValue()); } - s_logger.info("Defaulting to the range time backoff algorithm"); - _backoff = new RangeTimeBackoff(); + s_logger.info("Defaulting to the constant time backoff algorithm"); + _backoff = new ConstantTimeBackoff(); Map map = new HashMap<>(); - map.put("minSeconds", _properties.getProperty("backoff.min.seconds")); - map.put("maxSeconds", _properties.getProperty("backoff.max.seconds")); - _backoff.configure("RangeTimeBackoff", map); + map.put("seconds", _properties.getProperty("backoff.seconds")); + _backoff.configure("ConstantTimeBackoff", map); } private void launchAgent() throws ConfigurationException { diff --git a/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java b/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java deleted file mode 100644 index 668417c5f3f..00000000000 --- a/utils/src/test/java/com/cloud/utils/backoff/impl/RangeTimeBackoffTest.java +++ /dev/null @@ -1,87 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package com.cloud.utils.backoff.impl; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class RangeTimeBackoffTest { - - @Test - public void testWaitValidValue() { - RangeTimeBackoff backoff = new RangeTimeBackoff(); - Map map = new HashMap<>(); - int min = 1; - int max = 3; - map.put("minSeconds", String.valueOf(min)); - map.put("maxSeconds", String.valueOf(max)); - backoff.configure("RangeTimeBackoff", map); - long startTime = System.currentTimeMillis(); - backoff.waitBeforeRetry(); - long timeTaken = System.currentTimeMillis() - startTime; - Assert.assertTrue(timeTaken >= min * 1000L); - Assert.assertTrue(timeTaken <= max * 1000L); - } - - private void checkTimeTakenBetweenDelta(long timeTaken, int value) { - long min = (value * 1000L) - 10L; - long max = (value* 1000L) + 10L; - Assert.assertTrue(min <= timeTaken && timeTaken <= max); - } - - @Test - public void testWaitEmptyValue() { - RangeTimeBackoff backoff = new RangeTimeBackoff(); - Map map = new HashMap<>(); - map.put("minSeconds", ""); - map.put("maxSeconds", ""); - backoff.configure("RangeTimeBackoff", map); - long startTime = System.currentTimeMillis(); - backoff.waitBeforeRetry(); - checkTimeTakenBetweenDelta(System.currentTimeMillis() - startTime, RangeTimeBackoff.DEFAULT_MIN_TIME); - } - - @Test - public void testWaitNullValue() { - RangeTimeBackoff backoff = new RangeTimeBackoff(); - Map map = new HashMap<>(); - backoff.configure("RangeTimeBackoff", map); - long startTime = System.currentTimeMillis(); - backoff.waitBeforeRetry(); - checkTimeTakenBetweenDelta(System.currentTimeMillis() - startTime, RangeTimeBackoff.DEFAULT_MIN_TIME); - } - - @Test - public void testWaitVMinHigherThanMax() { - RangeTimeBackoff backoff = new RangeTimeBackoff(); - Map map = new HashMap<>(); - int min = 3; - int max = 2; - map.put("minSeconds", String.valueOf(min)); - map.put("maxSeconds", String.valueOf(max)); - backoff.configure("RangeTimeBackoff", map); - long startTime = System.currentTimeMillis(); - backoff.waitBeforeRetry(); - checkTimeTakenBetweenDelta(System.currentTimeMillis() - startTime, min); - } -} From bc42264b342d2cf476bf5f79d72caed53240d4ea Mon Sep 17 00:00:00 2001 From: Fabricio Duarte Date: Mon, 9 Sep 2024 12:07:50 -0300 Subject: [PATCH 61/62] Restore listNetworks behavior & clean up the code (#9461) Co-authored-by: Abhishek Kumar --- .../com/cloud/network/NetworkServiceImpl.java | 280 +++++++++--------- 1 file changed, 139 insertions(+), 141 deletions(-) diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index e1947c467c6..9654bb4fd2b 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -36,7 +36,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; @@ -76,6 +75,7 @@ import org.apache.cloudstack.network.NetworkPermissionVO; import org.apache.cloudstack.network.dao.NetworkPermissionDao; import org.apache.cloudstack.network.element.InternalLoadBalancerElementService; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; @@ -2050,6 +2050,9 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C Long associatedNetworkId = cmd.getAssociatedNetworkId(); String networkFilterStr = cmd.getNetworkFilter(); + boolean applyManualPagination = CollectionUtils.isNotEmpty(supportedServicesStr) || + Boolean.TRUE.equals(canUseForDeploy); + String vlanId = null; if (cmd instanceof ListNetworksCmdByAdmin) { vlanId = ((ListNetworksCmdByAdmin)cmd).getVlan(); @@ -2135,7 +2138,13 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C isRecursive = true; } - Filter searchFilter = new Filter(NetworkVO.class, "id", false, null, null); + Long offset = cmd.getStartIndex(); + Long limit = cmd.getPageSizeVal(); + if (applyManualPagination) { + offset = null; + limit = null; + } + Filter searchFilter = new Filter(NetworkVO.class, "id", false, offset, limit); SearchBuilder sb = _networksDao.createSearchBuilder(); if (forVpc != null) { @@ -2174,14 +2183,14 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C if (permittedAccounts.isEmpty()) { SearchBuilder domainSearch = _domainDao.createSearchBuilder(); domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); - sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); + sb.join("domain", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); } SearchBuilder accountSearch = _accountDao.createSearchBuilder(); accountSearch.and("typeNEQ", accountSearch.entity().getType(), SearchCriteria.Op.NEQ); accountSearch.and("typeEQ", accountSearch.entity().getType(), SearchCriteria.Op.EQ); - sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER); + sb.join("account", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER); if (associatedNetworkId != null) { SearchBuilder associatedNetworkSearch = _networkDetailsDao.createSearchBuilder(); @@ -2190,113 +2199,138 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C sb.join("associatedNetworkSearch", associatedNetworkSearch, sb.entity().getId(), associatedNetworkSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); } - List networksToReturn = new ArrayList(); - - if (isSystem == null || !isSystem) { - if (!permittedAccounts.isEmpty()) { - if (Arrays.asList(Network.NetworkFilter.Account, Network.NetworkFilter.AccountDomain, Network.NetworkFilter.All).contains(networkFilter)) { - //get account level networks - networksToReturn.addAll(listAccountSpecificNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, permittedAccounts)); - } - if (domainId != null && Arrays.asList(Network.NetworkFilter.Domain, Network.NetworkFilter.AccountDomain, Network.NetworkFilter.All).contains(networkFilter)) { - //get domain level networks - networksToReturn.addAll(listDomainLevelNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, domainId, false)); - } - if (Arrays.asList(Network.NetworkFilter.Shared, Network.NetworkFilter.All).contains(networkFilter)) { - // get shared networks - List sharedNetworks = listSharedNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, permittedAccounts); - addNetworksToReturnIfNotExist(networksToReturn, sharedNetworks); - - } - } else { - if (Arrays.asList(Network.NetworkFilter.Account, Network.NetworkFilter.AccountDomain, Network.NetworkFilter.All).contains(networkFilter)) { - //add account specific networks - networksToReturn.addAll(listAccountSpecificNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, path, isRecursive)); - } - if (Arrays.asList(Network.NetworkFilter.Domain, Network.NetworkFilter.AccountDomain, Network.NetworkFilter.All).contains(networkFilter)) { - //add domain specific networks of domain + parent domains - networksToReturn.addAll(listDomainSpecificNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, path, isRecursive)); - //add networks of subdomains - if (domainId == null) { - networksToReturn.addAll(listDomainLevelNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, caller.getDomainId(), true)); - } - } - if (Arrays.asList(Network.NetworkFilter.Shared, Network.NetworkFilter.All).contains(networkFilter)) { - // get shared networks - List sharedNetworks = listSharedNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, path, isRecursive); - addNetworksToReturnIfNotExist(networksToReturn, sharedNetworks); - } - } + Pair, Integer> result = new Pair<>(new ArrayList<>(), 0); + if (BooleanUtils.isTrue(isSystem)) { + SearchCriteria sc = createNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, + physicalNetworkId, networkOfferingId, null, restartRequired, specifyIpRanges, + vpcId, tags, display, vlanId, associatedNetworkId); + addProjectNetworksConditionToSearch(sc, true); + result = _networksDao.searchAndCount(sc, searchFilter); } else { - networksToReturn = _networksDao.search(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - null, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter); + SearchCriteria additionalSC = _networksDao.createSearchCriteria(); + + addAccountSpecificNetworksToSearch(additionalSC, sb, networkFilter, skipProjectNetworks, permittedAccounts, path, isRecursive); + addDomainSpecificNetworksToSearch(additionalSC, sb, networkFilter, permittedAccounts, domainId, path, isRecursive); + addSharedNetworksToSearch(additionalSC, sb, networkFilter, permittedAccounts, path, isRecursive); + + if (CollectionUtils.isNotEmpty(additionalSC.getValues())) { + SearchCriteria sc = createNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, + trafficType, physicalNetworkId, networkOfferingId, aclType, restartRequired, specifyIpRanges, vpcId, + tags, display, vlanId, associatedNetworkId); + sc.addAnd("id", SearchCriteria.Op.SC, additionalSC); + result = _networksDao.searchAndCount(sc, searchFilter); + } } + List networksToReturn = result.first(); if (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !networksToReturn.isEmpty()) { - List supportedNetworks = new ArrayList(); - Service[] suppportedServices = new Service[supportedServicesStr.size()]; + List supportedNetworks = new ArrayList<>(); + Service[] supportedServices = new Service[supportedServicesStr.size()]; int i = 0; for (String supportedServiceStr : supportedServicesStr) { Service service = Service.getService(supportedServiceStr); if (service == null) { throw new InvalidParameterValueException("Invalid service specified " + supportedServiceStr); } else { - suppportedServices[i] = service; + supportedServices[i] = service; } i++; } - for (NetworkVO network : networksToReturn) { - if (areServicesSupportedInNetwork(network.getId(), suppportedServices)) { + if (areServicesSupportedInNetwork(network.getId(), supportedServices)) { supportedNetworks.add(network); } } - networksToReturn = supportedNetworks; } if (canUseForDeploy != null) { - List networksForDeploy = new ArrayList(); + List networksForDeploy = new ArrayList<>(); for (NetworkVO network : networksToReturn) { if (_networkModel.canUseForDeploy(network) == canUseForDeploy) { networksForDeploy.add(network); } } - networksToReturn = networksForDeploy; } - //Now apply pagination - List wPagination = com.cloud.utils.StringUtils.applyPagination(networksToReturn, cmd.getStartIndex(), cmd.getPageSizeVal()); - if (wPagination != null) { - Pair, Integer> listWPagination = new Pair, Integer>(wPagination, networksToReturn.size()); - return listWPagination; + if (applyManualPagination) { + //Now apply pagination + List wPagination = com.cloud.utils.StringUtils.applyPagination(networksToReturn, cmd.getStartIndex(), cmd.getPageSizeVal()); + if (wPagination != null) { + Pair, Integer> listWPagination = new Pair<>(wPagination, networksToReturn.size()); + return listWPagination; + } + return new Pair<>(networksToReturn, networksToReturn.size()); } - return new Pair, Integer>(networksToReturn, networksToReturn.size()); + return new Pair<>(result.first(), result.second()); } - private void addNetworksToReturnIfNotExist(final List networksToReturn, final List sharedNetworks) { - Set networkIds = networksToReturn.stream() - .map(NetworkVO::getId) - .collect(Collectors.toSet()); - List sharedNetworksToReturn = sharedNetworks.stream() - .filter(network -> ! networkIds.contains(network.getId())) - .collect(Collectors.toList()); - networksToReturn.addAll(sharedNetworksToReturn); + private void addAccountSpecificNetworksToSearch(SearchCriteria additionalSC, SearchBuilder sb, + Network.NetworkFilter networkFilter, boolean skipProjectNetworks, + List permittedAccounts, String path, boolean isRecursive) { + if (!Arrays.asList(Network.NetworkFilter.Account, Network.NetworkFilter.AccountDomain, Network.NetworkFilter.All).contains(networkFilter)) { + return; + } + + SearchCriteria accountSC = sb.create(); + accountSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Account.toString()); + if (permittedAccounts.isEmpty()) { + if (path != null) { + // accountSC's WHERE clause gets OR-included in additionalSC's WHERE clause, which then gets AND-included + // in the main search criteria's WHERE clause. If we added the path filter as join parameters, it would not + // be present in the main search criteria. This is a way to add a condition that would normally go to accountSC's + // join parameters to its WHERE clause. + accountSC.getJoin("domain").addAnd("path", SearchCriteria.Op.LIKE, isRecursive ? path + "%" : path); + accountSC.addAnd("id", SearchCriteria.Op.SC, accountSC.getJoin("domain")); + } + } else { + accountSC.addAnd("accountId", SearchCriteria.Op.IN, permittedAccounts.toArray()); + } + addProjectNetworksConditionToSearch(accountSC, skipProjectNetworks); + additionalSC.addOr("id", SearchCriteria.Op.SC, accountSC); } - private SearchCriteria buildNetworkSearchCriteria(SearchBuilder sb, String keyword, Long id, - Boolean isSystem, Long zoneId, String guestIpType, String trafficType, Long physicalNetworkId, - Long networkOfferingId, String aclType, boolean skipProjectNetworks, Boolean restartRequired, - Boolean specifyIpRanges, Long vpcId, Map tags, Boolean display, String vlanId, Long associatedNetworkId) { + private void addDomainSpecificNetworksToSearch(SearchCriteria additionalSC, SearchBuilder sb, Network.NetworkFilter networkFilter, + List permittedAccounts, Long domainId, String path, boolean isRecursive) { + if (!Arrays.asList(Network.NetworkFilter.Domain, Network.NetworkFilter.AccountDomain, Network.NetworkFilter.All).contains(networkFilter)) { + return; + } + + if (permittedAccounts.isEmpty()) { + // Add domain specific networks of domain + parent domains + addDomainNetworksByDomainPathToSearch(additionalSC, sb, path, isRecursive); + if (domainId == null) { + // Add networks of subdomains + Account caller = CallContext.current().getCallingAccount(); + addDomainLevelNetworksToSearch(additionalSC, sb, caller.getDomainId(), true); + } + } else { + if (domainId != null) { + // Add domain level networks + addDomainLevelNetworksToSearch(additionalSC, sb, domainId, false); + } + } + } + + private void addSharedNetworksToSearch(SearchCriteria additionalSC, SearchBuilder sb, Network.NetworkFilter networkFilter, + List permittedAccounts, String path, boolean isRecursive) { + if (!Arrays.asList(Network.NetworkFilter.Shared, Network.NetworkFilter.All).contains(networkFilter)) { + return; + } + + if (permittedAccounts.isEmpty()) { + addSharedNetworksByDomainPathToSearch(additionalSC, sb, path, isRecursive); + } else { + addSharedNetworksByAccountsToSearch(additionalSC, sb, permittedAccounts); + } + } + + private SearchCriteria createNetworkSearchCriteria(SearchBuilder sb, String keyword, Long id, + Boolean isSystem, Long zoneId, String guestIpType, String trafficType, Long physicalNetworkId, + Long networkOfferingId, String aclType, Boolean restartRequired, + Boolean specifyIpRanges, Long vpcId, Map tags, Boolean display, String vlanId, Long associatedNetworkId) { SearchCriteria sc = sb.create(); @@ -2338,12 +2372,6 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C sc.addAnd("physicalNetworkId", SearchCriteria.Op.EQ, physicalNetworkId); } - if (skipProjectNetworks) { - sc.setJoinParameters("accountSearch", "typeNEQ", Account.Type.PROJECT); - } else { - sc.setJoinParameters("accountSearch", "typeEQ", Account.Type.PROJECT); - } - if (restartRequired != null) { sc.addAnd("restartRequired", SearchCriteria.Op.EQ, restartRequired); } @@ -2384,8 +2412,9 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C return sc; } - private List listDomainLevelNetworks(SearchCriteria sc, Filter searchFilter, long domainId, boolean parentDomainsOnly) { - List networkIds = new ArrayList(); + private void addDomainLevelNetworksToSearch(SearchCriteria additionalSC, SearchBuilder sb, + long domainId, boolean parentDomainsOnly) { + List networkIds = new ArrayList<>(); Set allowedDomains = _domainMgr.getDomainParentIds(domainId); List maps = _networkDomainDao.listDomainNetworkMapByDomain(allowedDomains.toArray()); @@ -2400,48 +2429,17 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } if (!networkIds.isEmpty()) { - SearchCriteria domainSC = _networksDao.createSearchCriteria(); + SearchCriteria domainSC = sb.create(); domainSC.addAnd("id", SearchCriteria.Op.IN, networkIds.toArray()); domainSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Domain.toString()); - - sc.addAnd("id", SearchCriteria.Op.SC, domainSC); - return _networksDao.search(sc, searchFilter); - } else { - return new ArrayList(); + addProjectNetworksConditionToSearch(domainSC, true); + additionalSC.addOr("id", SearchCriteria.Op.SC, domainSC); } } - private List listAccountSpecificNetworks(SearchCriteria sc, Filter searchFilter, List permittedAccounts) { - SearchCriteria accountSC = _networksDao.createSearchCriteria(); - if (!permittedAccounts.isEmpty()) { - accountSC.addAnd("accountId", SearchCriteria.Op.IN, permittedAccounts.toArray()); - } - - accountSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Account.toString()); - - sc.addAnd("id", SearchCriteria.Op.SC, accountSC); - return _networksDao.search(sc, searchFilter); - } - - private List listAccountSpecificNetworksByDomainPath(SearchCriteria sc, Filter searchFilter, String path, boolean isRecursive) { - SearchCriteria accountSC = _networksDao.createSearchCriteria(); - accountSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Account.toString()); - - if (path != null) { - if (isRecursive) { - sc.setJoinParameters("domainSearch", "path", path + "%"); - } else { - sc.setJoinParameters("domainSearch", "path", path); - } - } - - sc.addAnd("id", SearchCriteria.Op.SC, accountSC); - return _networksDao.search(sc, searchFilter); - } - - private List listDomainSpecificNetworksByDomainPath(SearchCriteria sc, Filter searchFilter, String path, boolean isRecursive) { - - Set allowedDomains = new HashSet(); + private void addDomainNetworksByDomainPathToSearch(SearchCriteria additionalSC, SearchBuilder sb, + String path, boolean isRecursive) { + Set allowedDomains = new HashSet<>(); if (path != null) { if (isRecursive) { allowedDomains = _domainMgr.getDomainChildrenIds(path); @@ -2451,39 +2449,40 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } } - List networkIds = new ArrayList(); + List networkIds = new ArrayList<>(); List maps = _networkDomainDao.listDomainNetworkMapByDomain(allowedDomains.toArray()); - for (NetworkDomainVO map : maps) { networkIds.add(map.getNetworkId()); } if (!networkIds.isEmpty()) { - SearchCriteria domainSC = _networksDao.createSearchCriteria(); + SearchCriteria domainSC = sb.create(); domainSC.addAnd("id", SearchCriteria.Op.IN, networkIds.toArray()); domainSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Domain.toString()); - - sc.addAnd("id", SearchCriteria.Op.SC, domainSC); - return _networksDao.search(sc, searchFilter); - } else { - return new ArrayList(); + addProjectNetworksConditionToSearch(domainSC, true); + additionalSC.addOr("id", SearchCriteria.Op.SC, domainSC); } } - private List listSharedNetworks(SearchCriteria sc, Filter searchFilter, List permittedAccounts) { + private void addProjectNetworksConditionToSearch(SearchCriteria sc, boolean skipProjectNetworks) { + sc.getJoin("account").addAnd("type", skipProjectNetworks ? Op.NEQ : Op.EQ, Account.Type.PROJECT); + sc.addAnd("id", Op.SC, sc.getJoin("account")); + } + + private void addSharedNetworksByAccountsToSearch(SearchCriteria additionalSC, SearchBuilder sb, + List permittedAccounts) { List sharedNetworkIds = _networkPermissionDao.listPermittedNetworkIdsByAccounts(permittedAccounts); if (!sharedNetworkIds.isEmpty()) { - SearchCriteria ssc = _networksDao.createSearchCriteria(); + SearchCriteria ssc = sb.create(); ssc.addAnd("id", SearchCriteria.Op.IN, sharedNetworkIds.toArray()); - sc.addAnd("id", SearchCriteria.Op.SC, ssc); - return _networksDao.search(sc, searchFilter); + addProjectNetworksConditionToSearch(ssc, true); + additionalSC.addOr("id", SearchCriteria.Op.SC, ssc); } - return new ArrayList(); } - private List listSharedNetworksByDomainPath(SearchCriteria sc, Filter searchFilter, String path, boolean isRecursive) { - Set allowedDomains = new HashSet(); + private void addSharedNetworksByDomainPathToSearch(SearchCriteria additionalSC, SearchBuilder sb, String path, boolean isRecursive) { + Set allowedDomains = new HashSet<>(); if (path != null) { if (isRecursive) { allowedDomains = _domainMgr.getDomainChildrenIds(path); @@ -2492,7 +2491,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C allowedDomains.add(domain.getId()); } } - List allowedDomainsList = new ArrayList(allowedDomains); + List allowedDomainsList = new ArrayList<>(allowedDomains); if (!allowedDomainsList.isEmpty()) { GenericSearchBuilder accountIdSearch = _accountDao.createSearchBuilder(Long.class); @@ -2505,13 +2504,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C List sharedNetworkIds = _networkPermissionDao.listPermittedNetworkIdsByAccounts(allowedAccountsList); if (!sharedNetworkIds.isEmpty()) { - SearchCriteria ssc = _networksDao.createSearchCriteria(); + SearchCriteria ssc = sb.create(); ssc.addAnd("id", SearchCriteria.Op.IN, sharedNetworkIds.toArray()); - sc.addAnd("id", SearchCriteria.Op.SC, ssc); - return _networksDao.search(sc, searchFilter); + addProjectNetworksConditionToSearch(ssc, true); + additionalSC.addOr("id", SearchCriteria.Op.SC, ssc); } } - return new ArrayList(); } @Override From 42111d8e8371e46b898452083417f250e5aaccbf Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 11 Oct 2024 12:30:57 +0530 Subject: [PATCH 62/62] fix EOF Signed-off-by: Abhishek Kumar --- agent/conf/agent.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties index ac98de0df8f..0ac62790a93 100644 --- a/agent/conf/agent.properties +++ b/agent/conf/agent.properties @@ -423,4 +423,4 @@ iscsi.session.cleanup.enabled=false #ssl.handshake.timeout= # Wait(in seconds) during agent reconnections -#backoff.seconds= \ No newline at end of file +#backoff.seconds=