From d45a6d3c2cd931e0d34782db192f8acb251353cf Mon Sep 17 00:00:00 2001 From: Ruirui Zhang Date: Tue, 20 Aug 2024 22:19:17 -0700 Subject: [PATCH] Add Settings related to Workload Management feature (#15028) Signed-off-by: Ruirui Zhang * add QeryGroup Service tests Signed-off-by: Ruirui Zhang * add PR to changelog Signed-off-by: Ruirui Zhang * change the test directory Signed-off-by: Ruirui Zhang * modify comments to be more specific Signed-off-by: Ruirui Zhang * add test coverage Signed-off-by: Ruirui Zhang * remove QUERY_GROUP_RUN_INTERVAL_SETTING as we'll define it in QueryGroupService Signed-off-by: Ruirui Zhang * address comments Signed-off-by: Ruirui Zhang (cherry picked from commit 01184decb897dcdfc1b1d36980c4fc4eeddb8e54) --- CHANGELOG.md | 1 + .../common/settings/ClusterSettings.java | 9 +- .../wlm/WorkloadManagementSettings.java | 256 ++++++++++++++++++ .../wlm/WorkloadManagementSettingsTests.java | 241 +++++++++++++++++ 4 files changed, 506 insertions(+), 1 deletion(-) create mode 100644 server/src/main/java/org/opensearch/wlm/WorkloadManagementSettings.java create mode 100644 server/src/test/java/org/opensearch/wlm/WorkloadManagementSettingsTests.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 5509e3a4a160f..e1f4a90cf2f7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased 2.x] ### Added - Add fingerprint ingest processor ([#13724](https://github.com/opensearch-project/OpenSearch/pull/13724)) +- [Workload Management] Add Settings for Workload Management feature ([#15028](https://github.com/opensearch-project/OpenSearch/pull/15028)) - [Remote Store] Rate limiter for remote store low priority uploads ([#14374](https://github.com/opensearch-project/OpenSearch/pull/14374/)) - Apply the date histogram rewrite optimization to range aggregation ([#13865](https://github.com/opensearch-project/OpenSearch/pull/13865)) - [Writable Warm] Add composite directory implementation and integrate it with FileCache ([12782](https://github.com/opensearch-project/OpenSearch/pull/12782)) diff --git a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java index 84eea3ed0a7f2..76af84b3e39fe 100644 --- a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java +++ b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java @@ -172,6 +172,7 @@ import org.opensearch.transport.SniffConnectionStrategy; import org.opensearch.transport.TransportSettings; import org.opensearch.watcher.ResourceWatcherService; +import org.opensearch.wlm.WorkloadManagementSettings; import java.util.Arrays; import java.util.Collections; @@ -756,7 +757,13 @@ public void apply(Settings value, Settings current, Settings previous) { RemoteStoreSettings.CLUSTER_REMOTE_STORE_PATH_HASH_ALGORITHM_SETTING, RemoteStoreSettings.CLUSTER_REMOTE_MAX_TRANSLOG_READERS, RemoteStoreSettings.CLUSTER_REMOTE_STORE_TRANSLOG_METADATA, - SearchService.CLUSTER_ALLOW_DERIVED_FIELD_SETTING + SearchService.CLUSTER_ALLOW_DERIVED_FIELD_SETTING, + + // WorkloadManagement settings + WorkloadManagementSettings.NODE_LEVEL_CPU_REJECTION_THRESHOLD, + WorkloadManagementSettings.NODE_LEVEL_CPU_CANCELLATION_THRESHOLD, + WorkloadManagementSettings.NODE_LEVEL_MEMORY_REJECTION_THRESHOLD, + WorkloadManagementSettings.NODE_LEVEL_MEMORY_CANCELLATION_THRESHOLD ) ) ); diff --git a/server/src/main/java/org/opensearch/wlm/WorkloadManagementSettings.java b/server/src/main/java/org/opensearch/wlm/WorkloadManagementSettings.java new file mode 100644 index 0000000000000..b104925df77b3 --- /dev/null +++ b/server/src/main/java/org/opensearch/wlm/WorkloadManagementSettings.java @@ -0,0 +1,256 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.wlm; + +import org.opensearch.common.settings.ClusterSettings; +import org.opensearch.common.settings.Setting; +import org.opensearch.common.settings.Settings; + +/** + * Main class to declare Workload Management related settings + */ +public class WorkloadManagementSettings { + private static final Double DEFAULT_NODE_LEVEL_MEMORY_REJECTION_THRESHOLD = 0.8; + private static final Double DEFAULT_NODE_LEVEL_MEMORY_CANCELLATION_THRESHOLD = 0.9; + private static final Double DEFAULT_NODE_LEVEL_CPU_REJECTION_THRESHOLD = 0.8; + private static final Double DEFAULT_NODE_LEVEL_CPU_CANCELLATION_THRESHOLD = 0.9; + public static final double NODE_LEVEL_MEMORY_CANCELLATION_THRESHOLD_MAX_VALUE = 0.95; + public static final double NODE_LEVEL_MEMORY_REJECTION_THRESHOLD_MAX_VALUE = 0.9; + public static final double NODE_LEVEL_CPU_CANCELLATION_THRESHOLD_MAX_VALUE = 0.95; + public static final double NODE_LEVEL_CPU_REJECTION_THRESHOLD_MAX_VALUE = 0.9; + + private Double nodeLevelMemoryCancellationThreshold; + private Double nodeLevelMemoryRejectionThreshold; + private Double nodeLevelCpuCancellationThreshold; + private Double nodeLevelCpuRejectionThreshold; + + /** + * Setting name for node level memory based rejection threshold for QueryGroup service + */ + public static final String NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME = "wlm.query_group.node.memory_rejection_threshold"; + /** + * Setting to control the memory based rejection threshold + */ + public static final Setting NODE_LEVEL_MEMORY_REJECTION_THRESHOLD = Setting.doubleSetting( + NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME, + DEFAULT_NODE_LEVEL_MEMORY_REJECTION_THRESHOLD, + Setting.Property.Dynamic, + Setting.Property.NodeScope + ); + /** + * Setting name for node level cpu based rejection threshold for QueryGroup service + */ + public static final String NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME = "wlm.query_group.node.cpu_rejection_threshold"; + /** + * Setting to control the cpu based rejection threshold + */ + public static final Setting NODE_LEVEL_CPU_REJECTION_THRESHOLD = Setting.doubleSetting( + NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME, + DEFAULT_NODE_LEVEL_CPU_REJECTION_THRESHOLD, + Setting.Property.Dynamic, + Setting.Property.NodeScope + ); + /** + * Setting name for node level memory based cancellation threshold for QueryGroup service + */ + public static final String NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME = "wlm.query_group.node.memory_cancellation_threshold"; + /** + * Setting to control the memory based cancellation threshold + */ + public static final Setting NODE_LEVEL_MEMORY_CANCELLATION_THRESHOLD = Setting.doubleSetting( + NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME, + DEFAULT_NODE_LEVEL_MEMORY_CANCELLATION_THRESHOLD, + Setting.Property.Dynamic, + Setting.Property.NodeScope + ); + /** + * Setting name for node level cpu based cancellation threshold for QueryGroup service + */ + public static final String NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME = "wlm.query_group.node.cpu_cancellation_threshold"; + /** + * Setting to control the cpu based cancellation threshold + */ + public static final Setting NODE_LEVEL_CPU_CANCELLATION_THRESHOLD = Setting.doubleSetting( + NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME, + DEFAULT_NODE_LEVEL_CPU_CANCELLATION_THRESHOLD, + Setting.Property.Dynamic, + Setting.Property.NodeScope + ); + + /** + * QueryGroup service settings constructor + * @param settings - QueryGroup service settings + * @param clusterSettings - QueryGroup cluster settings + */ + public WorkloadManagementSettings(Settings settings, ClusterSettings clusterSettings) { + nodeLevelMemoryCancellationThreshold = NODE_LEVEL_MEMORY_CANCELLATION_THRESHOLD.get(settings); + nodeLevelMemoryRejectionThreshold = NODE_LEVEL_MEMORY_REJECTION_THRESHOLD.get(settings); + nodeLevelCpuCancellationThreshold = NODE_LEVEL_CPU_CANCELLATION_THRESHOLD.get(settings); + nodeLevelCpuRejectionThreshold = NODE_LEVEL_CPU_REJECTION_THRESHOLD.get(settings); + + ensureRejectionThresholdIsLessThanCancellation( + nodeLevelMemoryRejectionThreshold, + nodeLevelMemoryCancellationThreshold, + NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME, + NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME + ); + ensureRejectionThresholdIsLessThanCancellation( + nodeLevelCpuRejectionThreshold, + nodeLevelCpuCancellationThreshold, + NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME, + NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME + ); + + clusterSettings.addSettingsUpdateConsumer(NODE_LEVEL_MEMORY_CANCELLATION_THRESHOLD, this::setNodeLevelMemoryCancellationThreshold); + clusterSettings.addSettingsUpdateConsumer(NODE_LEVEL_MEMORY_REJECTION_THRESHOLD, this::setNodeLevelMemoryRejectionThreshold); + clusterSettings.addSettingsUpdateConsumer(NODE_LEVEL_CPU_CANCELLATION_THRESHOLD, this::setNodeLevelCpuCancellationThreshold); + clusterSettings.addSettingsUpdateConsumer(NODE_LEVEL_CPU_REJECTION_THRESHOLD, this::setNodeLevelCpuRejectionThreshold); + } + + /** + * Method to get the node level memory based cancellation threshold + * @return current node level memory based cancellation threshold + */ + public Double getNodeLevelMemoryCancellationThreshold() { + return nodeLevelMemoryCancellationThreshold; + } + + /** + * Method to set the node level memory based cancellation threshold + * @param nodeLevelMemoryCancellationThreshold sets the new node level memory based cancellation threshold + * @throws IllegalArgumentException if the value is > 0.95 and cancellation < rejection threshold + */ + public void setNodeLevelMemoryCancellationThreshold(Double nodeLevelMemoryCancellationThreshold) { + if (Double.compare(nodeLevelMemoryCancellationThreshold, NODE_LEVEL_MEMORY_CANCELLATION_THRESHOLD_MAX_VALUE) > 0) { + throw new IllegalArgumentException( + NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME + " value cannot be greater than 0.95 as it can result in a node drop" + ); + } + + ensureRejectionThresholdIsLessThanCancellation( + nodeLevelMemoryRejectionThreshold, + nodeLevelMemoryCancellationThreshold, + NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME, + NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME + ); + + this.nodeLevelMemoryCancellationThreshold = nodeLevelMemoryCancellationThreshold; + } + + /** + * Method to get the node level cpu based cancellation threshold + * @return current node level cpu based cancellation threshold + */ + public Double getNodeLevelCpuCancellationThreshold() { + return nodeLevelCpuCancellationThreshold; + } + + /** + * Method to set the node level cpu based cancellation threshold + * @param nodeLevelCpuCancellationThreshold sets the new node level cpu based cancellation threshold + * @throws IllegalArgumentException if the value is > 0.95 and cancellation < rejection threshold + */ + public void setNodeLevelCpuCancellationThreshold(Double nodeLevelCpuCancellationThreshold) { + if (Double.compare(nodeLevelCpuCancellationThreshold, NODE_LEVEL_CPU_CANCELLATION_THRESHOLD_MAX_VALUE) > 0) { + throw new IllegalArgumentException( + NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME + " value cannot be greater than 0.95 as it can result in a node drop" + ); + } + + ensureRejectionThresholdIsLessThanCancellation( + nodeLevelCpuRejectionThreshold, + nodeLevelCpuCancellationThreshold, + NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME, + NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME + ); + + this.nodeLevelCpuCancellationThreshold = nodeLevelCpuCancellationThreshold; + } + + /** + * Method to get the memory based node level rejection threshold + * @return the current memory based node level rejection threshold + */ + public Double getNodeLevelMemoryRejectionThreshold() { + return nodeLevelMemoryRejectionThreshold; + } + + /** + * Method to set the node level memory based rejection threshold + * @param nodeLevelMemoryRejectionThreshold sets the new memory based rejection threshold + * @throws IllegalArgumentException if rejection > 0.90 and rejection < cancellation threshold + */ + public void setNodeLevelMemoryRejectionThreshold(Double nodeLevelMemoryRejectionThreshold) { + if (Double.compare(nodeLevelMemoryRejectionThreshold, NODE_LEVEL_MEMORY_REJECTION_THRESHOLD_MAX_VALUE) > 0) { + throw new IllegalArgumentException( + NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME + " value cannot be greater than 0.90 as it can result in a node drop" + ); + } + + ensureRejectionThresholdIsLessThanCancellation( + nodeLevelMemoryRejectionThreshold, + nodeLevelMemoryCancellationThreshold, + NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME, + NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME + ); + + this.nodeLevelMemoryRejectionThreshold = nodeLevelMemoryRejectionThreshold; + } + + /** + * Method to get the cpu based node level rejection threshold + * @return the current cpu based node level rejection threshold + */ + public Double getNodeLevelCpuRejectionThreshold() { + return nodeLevelCpuRejectionThreshold; + } + + /** + * Method to set the node level cpu based rejection threshold + * @param nodeLevelCpuRejectionThreshold sets the new cpu based rejection threshold + * @throws IllegalArgumentException if rejection > 0.90 and rejection < cancellation threshold + */ + public void setNodeLevelCpuRejectionThreshold(Double nodeLevelCpuRejectionThreshold) { + if (Double.compare(nodeLevelCpuRejectionThreshold, NODE_LEVEL_CPU_REJECTION_THRESHOLD_MAX_VALUE) > 0) { + throw new IllegalArgumentException( + NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME + " value cannot be greater than 0.90 as it can result in a node drop" + ); + } + + ensureRejectionThresholdIsLessThanCancellation( + nodeLevelCpuRejectionThreshold, + nodeLevelCpuCancellationThreshold, + NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME, + NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME + ); + + this.nodeLevelCpuRejectionThreshold = nodeLevelCpuRejectionThreshold; + } + + /** + * Method to validate that the cancellation threshold is greater than or equal to rejection threshold + * @param nodeLevelRejectionThreshold rejection threshold to be compared + * @param nodeLevelCancellationThreshold cancellation threshold to be compared + * @param rejectionThresholdSettingName name of the rejection threshold setting + * @param cancellationThresholdSettingName name of the cancellation threshold setting + * @throws IllegalArgumentException if cancellation threshold is less than rejection threshold + */ + private void ensureRejectionThresholdIsLessThanCancellation( + Double nodeLevelRejectionThreshold, + Double nodeLevelCancellationThreshold, + String rejectionThresholdSettingName, + String cancellationThresholdSettingName + ) { + if (Double.compare(nodeLevelCancellationThreshold, nodeLevelRejectionThreshold) < 0) { + throw new IllegalArgumentException( + cancellationThresholdSettingName + " value should not be less than " + rejectionThresholdSettingName + ); + } + } +} diff --git a/server/src/test/java/org/opensearch/wlm/WorkloadManagementSettingsTests.java b/server/src/test/java/org/opensearch/wlm/WorkloadManagementSettingsTests.java new file mode 100644 index 0000000000000..0f183555781d3 --- /dev/null +++ b/server/src/test/java/org/opensearch/wlm/WorkloadManagementSettingsTests.java @@ -0,0 +1,241 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.wlm; + +import org.opensearch.common.settings.ClusterSettings; +import org.opensearch.common.settings.Settings; +import org.opensearch.test.OpenSearchTestCase; + +import static org.opensearch.wlm.WorkloadManagementSettings.NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME; +import static org.opensearch.wlm.WorkloadManagementSettings.NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME; +import static org.opensearch.wlm.WorkloadManagementSettings.NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME; +import static org.opensearch.wlm.WorkloadManagementSettings.NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME; + +public class WorkloadManagementSettingsTests extends OpenSearchTestCase { + + /** + * Tests the invalid value for {@code wlm.query_group.node.memory_rejection_threshold} + * When the value is set more than {@code wlm.query_group.node.memory_cancellation_threshold} accidentally during + * new feature development. This test is to ensure that {@link WorkloadManagementSettings} holds the + * invariant {@code nodeLevelRejectionThreshold < nodeLevelCancellationThreshold} + */ + public void testInvalidMemoryInstantiationOfWorkloadManagementSettings() { + Settings settings = Settings.builder() + .put(NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME, 0.8) + .put(NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME, 0.7) + .build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + + assertThrows(IllegalArgumentException.class, () -> new WorkloadManagementSettings(settings, cs)); + } + + /** + * Tests the invalid value for {@code wlm.query_group.node.cpu_rejection_threshold} + * When the value is set more than {@code wlm.query_group.node.cpu_cancellation_threshold} accidentally during + * new feature development. This test is to ensure that {@link WorkloadManagementSettings} holds the + * invariant {@code nodeLevelRejectionThreshold < nodeLevelCancellationThreshold} + */ + public void testInvalidCpuInstantiationOfWorkloadManagementSettings() { + Settings settings = Settings.builder() + .put(NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME, 0.8) + .put(NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME, 0.7) + .build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + + assertThrows(IllegalArgumentException.class, () -> new WorkloadManagementSettings(settings, cs)); + } + + /** + * Tests the valid value for {@code wlm.query_group.node.cpu_rejection_threshold} + * Using setNodeLevelCpuRejectionThreshold function + */ + public void testValidNodeLevelCpuRejectionThresholdCase1() { + Settings settings = Settings.builder().put(NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME, 0.8).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + workloadManagementSettings.setNodeLevelCpuRejectionThreshold(0.7); + assertEquals(0.7, workloadManagementSettings.getNodeLevelCpuRejectionThreshold(), 1e-9); + } + + /** + * Tests the valid value for {@code wlm.query_group.node.cpu_rejection_threshold} + */ + public void testValidNodeLevelCpuRejectionThresholdCase2() { + Settings settings = Settings.builder().put(NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME, 0.79).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertEquals(0.79, workloadManagementSettings.getNodeLevelCpuRejectionThreshold(), 1e-9); + } + + /** + * Tests the invalid value for {@code wlm.query_group.node.cpu_rejection_threshold} + * When the value is set more than {@literal 0.9} + */ + public void testInvalidNodeLevelCpuRejectionThresholdCase1() { + Settings settings = Settings.builder().put(NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME, 0.8).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertThrows(IllegalArgumentException.class, () -> workloadManagementSettings.setNodeLevelCpuRejectionThreshold(0.95)); + } + + /** + * Tests the invalid value for {@code wlm.query_group.node.cpu_rejection_threshold} + * When the value is set more than {@code wlm.query_group.node.cpu_cancellation_threshold} + */ + public void testInvalidNodeLevelCpuRejectionThresholdCase2() { + Settings settings = Settings.builder() + .put(NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME, 0.7) + .put(NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME, 0.8) + .build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertThrows(IllegalArgumentException.class, () -> workloadManagementSettings.setNodeLevelCpuRejectionThreshold(0.85)); + } + + /** + * Tests the valid value for {@code wlm.query_group.node.cpu_cancellation_threshold} + */ + public void testValidNodeLevelCpuCancellationThresholdCase1() { + Settings settings = Settings.builder().put(NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME, 0.8).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertEquals(0.8, workloadManagementSettings.getNodeLevelCpuRejectionThreshold(), 1e-9); + } + + /** + * Tests the valid value for {@code wlm.query_group.node.cpu_cancellation_threshold} + * Using setNodeLevelCpuCancellationThreshold function + */ + public void testValidNodeLevelCpuCancellationThresholdCase2() { + Settings settings = Settings.builder().put(NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME, 0.8).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + workloadManagementSettings.setNodeLevelCpuCancellationThreshold(0.83); + assertEquals(0.83, workloadManagementSettings.getNodeLevelCpuCancellationThreshold(), 1e-9); + } + + /** + * Tests the invalid value for {@code wlm.query_group.node.cpu_cancellation_threshold} + * When the value is set more than {@literal 0.95} + */ + public void testInvalidNodeLevelCpuCancellationThresholdCase1() { + Settings settings = Settings.builder().put(NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME, 0.9).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertThrows(IllegalArgumentException.class, () -> workloadManagementSettings.setNodeLevelCpuCancellationThreshold(0.96)); + } + + /** + * Tests the invalid value for {@code wlm.query_group.node.cpu_cancellation_threshold} + * When the value is set less than {@code wlm.query_group.node.cpu_rejection_threshold} + */ + public void testInvalidNodeLevelCpuCancellationThresholdCase2() { + Settings settings = Settings.builder() + .put(NODE_CPU_REJECTION_THRESHOLD_SETTING_NAME, 0.7) + .put(NODE_CPU_CANCELLATION_THRESHOLD_SETTING_NAME, 0.8) + .build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertThrows(IllegalArgumentException.class, () -> workloadManagementSettings.setNodeLevelCpuCancellationThreshold(0.65)); + } + + /** + * Tests the valid value for {@code wlm.query_group.node.memory_cancellation_threshold} + */ + public void testValidNodeLevelMemoryCancellationThresholdCase1() { + Settings settings = Settings.builder().put(NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME, 0.8).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertEquals(0.8, workloadManagementSettings.getNodeLevelMemoryCancellationThreshold(), 1e-9); + } + + /** + * Tests the valid value for {@code wlm.query_group.node.memory_cancellation_threshold} + * Using setNodeLevelMemoryCancellationThreshold function + */ + public void testValidNodeLevelMemoryCancellationThresholdCase2() { + Settings settings = Settings.builder().put(NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME, 0.8).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + workloadManagementSettings.setNodeLevelMemoryCancellationThreshold(0.83); + assertEquals(0.83, workloadManagementSettings.getNodeLevelMemoryCancellationThreshold(), 1e-9); + } + + /** + * Tests the invalid value for {@code wlm.query_group.node.memory_cancellation_threshold} + * When the value is set more than {@literal 0.95} + */ + public void testInvalidNodeLevelMemoryCancellationThresholdCase1() { + Settings settings = Settings.builder().put(NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME, 0.9).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertThrows(IllegalArgumentException.class, () -> workloadManagementSettings.setNodeLevelMemoryCancellationThreshold(0.96)); + } + + /** + * Tests the invalid value for {@code wlm.query_group.node.memory_cancellation_threshold} + * When the value is set less than {@code wlm.query_group.node.memory_rejection_threshold} + */ + public void testInvalidNodeLevelMemoryCancellationThresholdCase2() { + Settings settings = Settings.builder() + .put(NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME, 0.7) + .put(NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME, 0.8) + .build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertThrows(IllegalArgumentException.class, () -> workloadManagementSettings.setNodeLevelMemoryCancellationThreshold(0.65)); + } + + /** + * Tests the valid value for {@code wlm.query_group.node.memory_rejection_threshold} + */ + public void testValidNodeLevelMemoryRejectionThresholdCase1() { + Settings settings = Settings.builder().put(NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME, 0.79).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertEquals(0.79, workloadManagementSettings.getNodeLevelMemoryRejectionThreshold(), 1e-9); + } + + /** + * Tests the valid value for {@code wlm.query_group.node.memory_rejection_threshold} + * Using setNodeLevelMemoryRejectionThreshold function + */ + public void testValidNodeLevelMemoryRejectionThresholdCase2() { + Settings settings = Settings.builder().put(NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME, 0.9).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + workloadManagementSettings.setNodeLevelMemoryRejectionThreshold(0.86); + assertEquals(0.86, workloadManagementSettings.getNodeLevelMemoryRejectionThreshold(), 1e-9); + } + + /** + * Tests the invalid value for {@code wlm.query_group.node.memory_rejection_threshold} + * When the value is set more than {@literal 0.9} + */ + public void testInvalidNodeLevelMemoryRejectionThresholdCase1() { + Settings settings = Settings.builder().put(NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME, 0.9).build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertThrows(IllegalArgumentException.class, () -> workloadManagementSettings.setNodeLevelMemoryRejectionThreshold(0.92)); + } + + /** + * Tests the invalid value for {@code wlm.query_group.node.memory_rejection_threshold} + * When the value is set more than {@code wlm.query_group.node.memory_cancellation_threshold} + */ + public void testInvalidNodeLevelMemoryRejectionThresholdCase2() { + Settings settings = Settings.builder() + .put(NODE_MEMORY_REJECTION_THRESHOLD_SETTING_NAME, 0.7) + .put(NODE_MEMORY_CANCELLATION_THRESHOLD_SETTING_NAME, 0.8) + .build(); + ClusterSettings cs = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + WorkloadManagementSettings workloadManagementSettings = new WorkloadManagementSettings(settings, cs); + assertThrows(IllegalArgumentException.class, () -> workloadManagementSettings.setNodeLevelMemoryRejectionThreshold(0.85)); + } +}