From 4f40eae1c406834f2539317b5a8f33031e70bd5c Mon Sep 17 00:00:00 2001 From: Vishesh Date: Wed, 10 Jan 2024 17:52:46 +0530 Subject: [PATCH] DRS: Use free metrics insteado of used for computation (#8458) This PR makes changes to use cluster's free metrics instead of used while computing imbalance for the cluster. This allows DRS to run for clusters where hosts doesn't have the same amount of metrics. --- .../cluster/ClusterDrsAlgorithm.java | 36 +++++++++---------- .../cloudstack/cluster/BalancedTest.java | 20 +++++------ .../cloudstack/cluster/CondensedTest.java | 20 +++++------ .../cluster/ClusterDrsServiceImpl.java | 12 +++---- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsAlgorithm.java b/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsAlgorithm.java index ad5edc9224b..889c49298ec 100644 --- a/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsAlgorithm.java +++ b/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsAlgorithm.java @@ -65,18 +65,18 @@ public interface ClusterDrsAlgorithm extends Adapter { * the service offering for the virtual machine * @param destHost * the destination host for the virtual machine - * @param hostCpuUsedMap - * a map of host IDs to the amount of CPU used on each host - * @param hostMemoryUsedMap - * a map of host IDs to the amount of memory used on each host + * @param hostCpuFreeMap + * a map of host IDs to the amount of CPU free on each host + * @param hostMemoryFreeMap + * a map of host IDs to the amount of memory free on each host * @param requiresStorageMotion * whether storage motion is required for the virtual machine * * @return a ternary containing improvement, cost, benefit */ Ternary getMetrics(long clusterId, VirtualMachine vm, ServiceOffering serviceOffering, - Host destHost, Map hostCpuUsedMap, - Map hostMemoryUsedMap, Boolean requiresStorageMotion); + Host destHost, Map hostCpuFreeMap, + Map hostMemoryFreeMap, Boolean requiresStorageMotion); /** * Calculates the imbalance of the cluster after a virtual machine migration. @@ -87,30 +87,30 @@ public interface ClusterDrsAlgorithm extends Adapter { * the virtual machine being migrated * @param destHost * the destination host for the virtual machine - * @param hostCpuUsedMap - * a map of host IDs to the amount of CPU used on each host - * @param hostMemoryUsedMap - * a map of host IDs to the amount of memory used on each host + * @param hostCpuFreeMap + * a map of host IDs to the amount of CPU free on each host + * @param hostMemoryFreeMap + * a map of host IDs to the amount of memory free on each host * * @return a pair containing the CPU and memory imbalance of the cluster after the migration */ default Pair getImbalancePostMigration(ServiceOffering serviceOffering, VirtualMachine vm, - Host destHost, Map hostCpuUsedMap, - Map hostMemoryUsedMap) { + Host destHost, Map hostCpuFreeMap, + Map hostMemoryFreeMap) { List postCpuList = new ArrayList<>(); List postMemoryList = new ArrayList<>(); final int vmCpu = serviceOffering.getCpu() * serviceOffering.getSpeed(); final long vmRam = serviceOffering.getRamSize() * 1024L * 1024L; - for (Long hostId : hostCpuUsedMap.keySet()) { - long cpu = hostCpuUsedMap.get(hostId); - long memory = hostMemoryUsedMap.get(hostId); + for (Long hostId : hostCpuFreeMap.keySet()) { + long cpu = hostCpuFreeMap.get(hostId); + long memory = hostMemoryFreeMap.get(hostId); if (hostId == destHost.getId()) { - postCpuList.add(cpu + vmCpu); - postMemoryList.add(memory + vmRam); - } else if (hostId.equals(vm.getHostId())) { postCpuList.add(cpu - vmCpu); postMemoryList.add(memory - vmRam); + } else if (hostId.equals(vm.getHostId())) { + postCpuList.add(cpu + vmCpu); + postMemoryList.add(memory + vmRam); } else { postCpuList.add(cpu); postMemoryList.add(memory); diff --git a/plugins/drs/cluster/balanced/src/test/java/org/apache/cloudstack/cluster/BalancedTest.java b/plugins/drs/cluster/balanced/src/test/java/org/apache/cloudstack/cluster/BalancedTest.java index 4b84049e49a..0da807e65c3 100644 --- a/plugins/drs/cluster/balanced/src/test/java/org/apache/cloudstack/cluster/BalancedTest.java +++ b/plugins/drs/cluster/balanced/src/test/java/org/apache/cloudstack/cluster/BalancedTest.java @@ -68,7 +68,7 @@ public class BalancedTest { List cpuList, memoryList; - Map hostCpuUsedMap, hostMemoryUsedMap; + Map hostCpuFreeMap, hostMemoryFreeMap; @Mock @@ -105,13 +105,13 @@ public class BalancedTest { cpuList = Arrays.asList(1L, 2L); memoryList = Arrays.asList(512L, 2048L); - hostCpuUsedMap = new HashMap<>(); - hostCpuUsedMap.put(1L, 1000L); - hostCpuUsedMap.put(2L, 2000L); + hostCpuFreeMap = new HashMap<>(); + hostCpuFreeMap.put(1L, 2000L); + hostCpuFreeMap.put(2L, 1000L); - hostMemoryUsedMap = new HashMap<>(); - hostMemoryUsedMap.put(1L, 512L * 1024L * 1024L); - hostMemoryUsedMap.put(2L, 2048L * 1024L * 1024L); + hostMemoryFreeMap = new HashMap<>(); + hostMemoryFreeMap.put(1L, 2048L * 1024L * 1024L); + hostMemoryFreeMap.put(2L, 512L * 1024L * 1024L); } private void overrideDefaultConfigValue(final ConfigKey configKey, final String name, @@ -191,7 +191,7 @@ public class BalancedTest { public void getMetricsWithCpu() throws NoSuchFieldException, IllegalAccessException { overrideDefaultConfigValue(ClusterDrsMetric, "_defaultValue", "cpu"); Ternary result = balanced.getMetrics(clusterId, vm3, serviceOffering, destHost, - hostCpuUsedMap, hostMemoryUsedMap, false); + hostCpuFreeMap, hostMemoryFreeMap, false); assertEquals(0.0, result.first(), 0.01); assertEquals(0.0, result.second(), 0.0); assertEquals(1.0, result.third(), 0.0); @@ -205,7 +205,7 @@ public class BalancedTest { public void getMetricsWithMemory() throws NoSuchFieldException, IllegalAccessException { overrideDefaultConfigValue(ClusterDrsMetric, "_defaultValue", "memory"); Ternary result = balanced.getMetrics(clusterId, vm3, serviceOffering, destHost, - hostCpuUsedMap, hostMemoryUsedMap, false); + hostCpuFreeMap, hostMemoryFreeMap, false); assertEquals(0.4, result.first(), 0.01); assertEquals(0, result.second(), 0.0); assertEquals(1, result.third(), 0.0); @@ -219,7 +219,7 @@ public class BalancedTest { public void getMetricsWithDefault() throws NoSuchFieldException, IllegalAccessException { overrideDefaultConfigValue(ClusterDrsMetric, "_defaultValue", "both"); Ternary result = balanced.getMetrics(clusterId, vm3, serviceOffering, destHost, - hostCpuUsedMap, hostMemoryUsedMap, false); + hostCpuFreeMap, hostMemoryFreeMap, false); assertEquals(0.4, result.first(), 0.01); assertEquals(0, result.second(), 0.0); assertEquals(1, result.third(), 0.0); diff --git a/plugins/drs/cluster/condensed/src/test/java/org/apache/cloudstack/cluster/CondensedTest.java b/plugins/drs/cluster/condensed/src/test/java/org/apache/cloudstack/cluster/CondensedTest.java index d8cf581768a..0ba2b66379a 100644 --- a/plugins/drs/cluster/condensed/src/test/java/org/apache/cloudstack/cluster/CondensedTest.java +++ b/plugins/drs/cluster/condensed/src/test/java/org/apache/cloudstack/cluster/CondensedTest.java @@ -66,7 +66,7 @@ public class CondensedTest { List cpuList, memoryList; - Map hostCpuUsedMap, hostMemoryUsedMap; + Map hostCpuFreeMap, hostMemoryFreeMap; private AutoCloseable closeable; @@ -98,13 +98,13 @@ public class CondensedTest { cpuList = Arrays.asList(1L, 2L); memoryList = Arrays.asList(512L, 2048L); - hostCpuUsedMap = new HashMap<>(); - hostCpuUsedMap.put(1L, 1000L); - hostCpuUsedMap.put(2L, 2000L); + hostCpuFreeMap = new HashMap<>(); + hostCpuFreeMap.put(1L, 2000L); + hostCpuFreeMap.put(2L, 1000L); - hostMemoryUsedMap = new HashMap<>(); - hostMemoryUsedMap.put(1L, 512L * 1024L * 1024L); - hostMemoryUsedMap.put(2L, 2048L * 1024L * 1024L); + hostMemoryFreeMap = new HashMap<>(); + hostMemoryFreeMap.put(1L, 2048L * 1024L * 1024L); + hostMemoryFreeMap.put(2L, 512L * 1024L * 1024L); } private void overrideDefaultConfigValue(final ConfigKey configKey, @@ -185,7 +185,7 @@ public class CondensedTest { public void getMetricsWithCpu() throws NoSuchFieldException, IllegalAccessException { overrideDefaultConfigValue(ClusterDrsMetric, "_defaultValue", "cpu"); Ternary result = condensed.getMetrics(clusterId, vm3, serviceOffering, destHost, - hostCpuUsedMap, hostMemoryUsedMap, false); + hostCpuFreeMap, hostMemoryFreeMap, false); assertEquals(0.0, result.first(), 0.0); assertEquals(0, result.second(), 0.0); assertEquals(1, result.third(), 0.0); @@ -199,7 +199,7 @@ public class CondensedTest { public void getMetricsWithMemory() throws NoSuchFieldException, IllegalAccessException { overrideDefaultConfigValue(ClusterDrsMetric, "_defaultValue", "memory"); Ternary result = condensed.getMetrics(clusterId, vm3, serviceOffering, destHost, - hostCpuUsedMap, hostMemoryUsedMap, false); + hostCpuFreeMap, hostMemoryFreeMap, false); assertEquals(-0.4, result.first(), 0.01); assertEquals(0, result.second(), 0.0); assertEquals(1, result.third(), 0.0); @@ -213,7 +213,7 @@ public class CondensedTest { public void getMetricsWithDefault() throws NoSuchFieldException, IllegalAccessException { overrideDefaultConfigValue(ClusterDrsMetric, "_defaultValue", "both"); Ternary result = condensed.getMetrics(clusterId, vm3, serviceOffering, destHost, - hostCpuUsedMap, hostMemoryUsedMap, false); + hostCpuFreeMap, hostMemoryFreeMap, false); assertEquals(-0.4, result.first(), 0.0001); assertEquals(0, result.second(), 0.0); assertEquals(1, result.third(), 0.0); diff --git a/server/src/main/java/org/apache/cloudstack/cluster/ClusterDrsServiceImpl.java b/server/src/main/java/org/apache/cloudstack/cluster/ClusterDrsServiceImpl.java index 3ebb97ae4f0..f949233e8e8 100644 --- a/server/src/main/java/org/apache/cloudstack/cluster/ClusterDrsServiceImpl.java +++ b/server/src/main/java/org/apache/cloudstack/cluster/ClusterDrsServiceImpl.java @@ -354,9 +354,9 @@ public class ClusterDrsServiceImpl extends ManagerBase implements ClusterDrsServ hostList.stream().map(HostVO::getId).toArray(Long[]::new)); Map hostCpuMap = hostJoinList.stream().collect(Collectors.toMap(HostJoinVO::getId, - hostJoin -> hostJoin.getCpuUsedCapacity() + hostJoin.getCpuReservedCapacity())); + hostJoin -> hostJoin.getCpus() * hostJoin.getSpeed() - hostJoin.getCpuReservedCapacity() - hostJoin.getCpuUsedCapacity())); Map hostMemoryMap = hostJoinList.stream().collect(Collectors.toMap(HostJoinVO::getId, - hostJoin -> hostJoin.getMemUsedCapacity() + hostJoin.getMemReservedCapacity())); + hostJoin -> hostJoin.getTotalMemory() - hostJoin.getMemUsedCapacity() - hostJoin.getMemReservedCapacity())); Map vmIdServiceOfferingMap = new HashMap<>(); @@ -387,10 +387,10 @@ public class ClusterDrsServiceImpl extends ManagerBase implements ClusterDrsServ long vmCpu = (long) serviceOffering.getCpu() * serviceOffering.getSpeed(); long vmMemory = serviceOffering.getRamSize() * 1024L * 1024L; - hostCpuMap.put(vm.getHostId(), hostCpuMap.get(vm.getHostId()) - vmCpu); - hostCpuMap.put(destHost.getId(), hostCpuMap.get(destHost.getId()) + vmCpu); - hostMemoryMap.put(vm.getHostId(), hostMemoryMap.get(vm.getHostId()) - vmMemory); - hostMemoryMap.put(destHost.getId(), hostMemoryMap.get(destHost.getId()) + vmMemory); + hostCpuMap.put(vm.getHostId(), hostCpuMap.get(vm.getHostId()) + vmCpu); + hostCpuMap.put(destHost.getId(), hostCpuMap.get(destHost.getId()) - vmCpu); + hostMemoryMap.put(vm.getHostId(), hostMemoryMap.get(vm.getHostId()) + vmMemory); + hostMemoryMap.put(destHost.getId(), hostMemoryMap.get(destHost.getId()) - vmMemory); vm.setHostId(destHost.getId()); iteration++; }