summaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorHarald Musum <musum@verizonmedia.com>2021-07-01 15:18:38 +0200
committerHarald Musum <musum@verizonmedia.com>2021-07-01 15:18:38 +0200
commit81a2dafda8b20a4eb6dcf65290af50171f7c9724 (patch)
tree5f1755e2d3d01aef829583469fe9bdf9e3a69e09 /config-model
parent606a9a60504c27f5d44709a085be829ff379268b (diff)
Add feature flags for disk and memory resource limits
Used when finding out when to block feed
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java14
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/ClusterResourceLimits.java40
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java4
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/content/ClusterResourceLimitsTest.java59
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/content/FleetControllerClusterTest.java6
5 files changed, 109 insertions, 14 deletions
diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java
index 308dcf25d2a..62c192e2c99 100644
--- a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java
+++ b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java
@@ -64,6 +64,8 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea
private boolean allowDisableMtls = true;
private boolean dryRunOnnxOnSetup = false;
private List<X509Certificate> operatorCertificates = Collections.emptyList();
+ private double resourceLimitDisk = 0.8;
+ private double resourceLimitMemory = 0.8;
@Override public ModelContext.FeatureFlags featureFlags() { return this; }
@Override public boolean multitenant() { return multitenant; }
@@ -107,6 +109,8 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea
@Override public int maxConcurrentMergesPerNode() { return maxConcurrentMergesPerNode; }
@Override public int maxMergeQueueSize() { return maxMergeQueueSize; }
@Override public boolean dryRunOnnxOnSetup() { return dryRunOnnxOnSetup; }
+ @Override public double resourceLimitDisk() { return resourceLimitDisk; }
+ @Override public double resourceLimitMemory() { return resourceLimitMemory; }
public TestProperties setDryRunOnnxOnSetup(boolean value) {
dryRunOnnxOnSetup = value;
@@ -260,6 +264,16 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea
return this;
}
+ public TestProperties setResourceLimitDisk(double value) {
+ this.resourceLimitDisk = value;
+ return this;
+ }
+
+ public TestProperties setResourceLimitMemory(double value) {
+ this.resourceLimitMemory = value;
+ return this;
+ }
+
public static class Spec implements ConfigServerSpec {
private final String hostName;
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/ClusterResourceLimits.java b/config-model/src/main/java/com/yahoo/vespa/model/content/ClusterResourceLimits.java
index 638864d85bb..dc5e6c9baee 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/ClusterResourceLimits.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/ClusterResourceLimits.java
@@ -39,15 +39,21 @@ public class ClusterResourceLimits {
private final boolean hostedVespa;
private final boolean throwIfSpecified;
private final DeployLogger deployLogger;
+ private final double resourceLimitDisk;
+ private final double resourceLimitMemory;
private ResourceLimits.Builder ctrlBuilder = new ResourceLimits.Builder();
private ResourceLimits.Builder nodeBuilder = new ResourceLimits.Builder();
- public Builder(boolean enableFeedBlockInDistributor, boolean hostedVespa, boolean throwIfSpecified, DeployLogger deployLogger) {
+ public Builder(boolean enableFeedBlockInDistributor, boolean hostedVespa, boolean throwIfSpecified,
+ DeployLogger deployLogger, double resourceLimitDisk, double resourceLimitMemory) {
this.enableFeedBlockInDistributor = enableFeedBlockInDistributor;
this.hostedVespa = hostedVespa;
this.throwIfSpecified = throwIfSpecified;
this.deployLogger = deployLogger;
+ this.resourceLimitDisk = resourceLimitDisk;
+ this.resourceLimitMemory = resourceLimitMemory;
+ verifyLimits(resourceLimitDisk, resourceLimitMemory);
}
public ClusterResourceLimits build(ModelElement clusterElem) {
@@ -80,8 +86,14 @@ public class ClusterResourceLimits {
private void deriveLimits() {
if (enableFeedBlockInDistributor) {
// This also ensures that content nodes limits are derived according to the formula in calcContentNodeLimit().
- considerSettingDefaultClusterControllerLimit(ctrlBuilder.getDiskLimit(), nodeBuilder.getDiskLimit(), ctrlBuilder::setDiskLimit);
- considerSettingDefaultClusterControllerLimit(ctrlBuilder.getMemoryLimit(), nodeBuilder.getMemoryLimit(), ctrlBuilder::setMemoryLimit);
+ considerSettingDefaultClusterControllerLimit(ctrlBuilder.getDiskLimit(),
+ nodeBuilder.getDiskLimit(),
+ ctrlBuilder::setDiskLimit,
+ resourceLimitDisk);
+ considerSettingDefaultClusterControllerLimit(ctrlBuilder.getMemoryLimit(),
+ nodeBuilder.getMemoryLimit(),
+ ctrlBuilder::setMemoryLimit,
+ resourceLimitMemory);
}
deriveClusterControllerLimit(ctrlBuilder.getDiskLimit(), nodeBuilder.getDiskLimit(), ctrlBuilder::setDiskLimit);
@@ -93,10 +105,11 @@ public class ClusterResourceLimits {
private void considerSettingDefaultClusterControllerLimit(Optional<Double> clusterControllerLimit,
Optional<Double> contentNodeLimit,
- Consumer<Double> setter) {
+ Consumer<Double> setter,
+ double resourceLimit) {
// TODO: remove this when feed block in distributor is default enabled.
if (clusterControllerLimit.isEmpty() && contentNodeLimit.isEmpty()) {
- setter.accept(0.8);
+ setter.accept(resourceLimit);
}
}
@@ -120,10 +133,25 @@ public class ClusterResourceLimits {
}
private double calcContentNodeLimit(double clusterControllerLimit) {
- // Note that validation in the range [0.0-1.0] is handled by the rnc schema.
return clusterControllerLimit + ((1.0 - clusterControllerLimit) / 2);
}
+
+ private void verifyLimits(double resourceLimitDisk, double resourceLimitMemory) {
+ verifyLimitInRange(resourceLimitDisk, "disk");
+ verifyLimitInRange(resourceLimitMemory, "memory");
+ }
+
+ private void verifyLimitInRange(double limit, String type) {
+ String message = "Resource limit for " + type + " is set to illegal value " + limit +
+ ", but must be in the range [0.0, 1.0]";
+ if (limit < 0.0)
+ throw new IllegalArgumentException(message);
+
+ if (limit > 1.0)
+ throw new IllegalArgumentException(message);
+ }
+
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
index c298b7f5f5a..fabcbbcc9ec 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java
@@ -124,7 +124,9 @@ public class ContentCluster extends AbstractConfigProducer<AbstractConfigProduce
var resourceLimits = new ClusterResourceLimits.Builder(enableFeedBlockInDistributor,
stateIsHosted(deployState),
deployState.featureFlags().throwIfResourceLimitsSpecified(),
- deployState.getDeployLogger())
+ deployState.getDeployLogger(),
+ deployState.featureFlags().resourceLimitDisk(),
+ deployState.featureFlags().resourceLimitMemory())
.build(contentElement);
c.clusterControllerConfig = new ClusterControllerConfig.Builder(getClusterId(contentElement),
contentElement,
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/ClusterResourceLimitsTest.java b/config-model/src/test/java/com/yahoo/vespa/model/content/ClusterResourceLimitsTest.java
index 22618ea433b..c0b1a64bace 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/content/ClusterResourceLimitsTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/content/ClusterResourceLimitsTest.java
@@ -2,7 +2,9 @@
package com.yahoo.vespa.model.content;
import com.yahoo.config.application.api.DeployLogger;
+import com.yahoo.config.model.api.ModelContext;
import com.yahoo.config.model.application.provider.BaseDeployLogger;
+import com.yahoo.config.model.deploy.TestProperties;
import com.yahoo.searchdefinition.derived.TestableDeployLogger;
import com.yahoo.text.XML;
import com.yahoo.vespa.model.builder.xml.dom.ModelElement;
@@ -61,10 +63,13 @@ public class ClusterResourceLimitsTest {
return this;
}
public ClusterResourceLimits build() {
+ ModelContext.FeatureFlags featureFlags = new TestProperties();
var builder = new ClusterResourceLimits.Builder(enableFeedBlockInDistributor,
hostedVespa,
throwIfSpecified,
- new BaseDeployLogger());
+ new BaseDeployLogger(),
+ featureFlags.resourceLimitDisk(),
+ featureFlags.resourceLimitMemory());
builder.setClusterControllerBuilder(ctrlBuilder);
builder.setContentNodeBuilder(nodeBuilder);
return builder.build();
@@ -139,7 +144,7 @@ public class ClusterResourceLimitsTest {
}
@Test
- @Ignore // TODO: Remove hosted_limits_are_used_if_app_is_allowed_to_set_limits and enable this when code is fixed to do sp
+ @Ignore // TODO: Remove hosted_limits_are_used_if_app_is_allowed_to_set_limits and enable this when code is fixed to do so
public void hosted_log_when_resource_limits_are_specified() {
TestableDeployLogger logger = new TestableDeployLogger();
@@ -160,7 +165,7 @@ public class ClusterResourceLimitsTest {
}
@Test
- // TODO: Remove this and enable hosted_log_when_resource_limits_are_specified when code is fixed
+ // TODO: Remove this and enable hosted_log_when_resource_limits_are_specified when code is fixed to do so
public void hosted_limits_are_used_if_app_is_allowed_to_set_limits() {
TestableDeployLogger logger = new TestableDeployLogger();
@@ -173,8 +178,38 @@ public class ClusterResourceLimitsTest {
assertLimits(0.9, 0.96, limits.getContentNodeLimits());
}
+ @Test
+ public void hosted_limits_from_feature_flag_are_used() {
+ TestableDeployLogger logger = new TestableDeployLogger();
+
+ TestProperties featureFlags = new TestProperties();
+ featureFlags.setResourceLimitDisk(0.85);
+ featureFlags.setResourceLimitMemory(0.90);
+ var limits = hostedBuild(false, logger, featureFlags, false);
+
+ // Verify that limits from feature flags are used
+ assertLimits(0.85, 0.90, limits.getClusterControllerLimits());
+ assertLimits(0.925, 0.95, limits.getContentNodeLimits());
+ }
+
+ @Test
+ public void exception_is_thrown_when_resource_limits_are_out_of_range() {
+ TestableDeployLogger logger = new TestableDeployLogger();
+
+ TestProperties featureFlags = new TestProperties();
+ featureFlags.setResourceLimitDisk(1.1);
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage(containsString("Resource limit for disk is set to illegal value 1.1, but must be in the range [0.0, 1.0]"));
+ hostedBuild(false, logger, featureFlags, false);
+
+ featureFlags = new TestProperties();
+ featureFlags.setResourceLimitDisk(-0.1);
+ expectedException.expectMessage(containsString("Resource limit for disk is set to illegal value -0.1, but must be in the range [0.0, 1.0]"));
+ hostedBuild(false, logger, featureFlags, false);
+ }
+
private void hostedBuildAndThrowIfSpecified() {
- hostedBuild(true, new TestableDeployLogger());
+ hostedBuild(true, new TestableDeployLogger(), new TestProperties(), true);
}
private ClusterResourceLimits hostedBuildAndLogIfSpecified(DeployLogger deployLogger) {
@@ -182,6 +217,13 @@ public class ClusterResourceLimitsTest {
}
private ClusterResourceLimits hostedBuild(boolean throwIfSpecified, DeployLogger deployLogger) {
+ return hostedBuild(throwIfSpecified, deployLogger, new TestProperties(), true);
+ }
+
+ private ClusterResourceLimits hostedBuild(boolean throwIfSpecified,
+ DeployLogger deployLogger,
+ ModelContext.FeatureFlags featureFlags,
+ boolean limitsInXml) {
Document clusterXml = XML.getDocument("<cluster id=\"test\">" +
" <tuning>\n" +
" <resource-limits>\n" +
@@ -190,11 +232,16 @@ public class ClusterResourceLimitsTest {
" </tuning>\n" +
"</cluster>");
+ Document noLimitsXml = XML.getDocument("<cluster id=\"test\">" +
+ "</cluster>");
+
ClusterResourceLimits.Builder builder = new ClusterResourceLimits.Builder(true,
true,
throwIfSpecified,
- deployLogger);
- return builder.build(new ModelElement(clusterXml.getDocumentElement()));
+ deployLogger,
+ featureFlags.resourceLimitDisk(),
+ featureFlags.resourceLimitMemory());
+ return builder.build(new ModelElement((limitsInXml ? clusterXml : noLimitsXml).getDocumentElement()));
}
private void assertLimits(Double expCtrlDisk, Double expCtrlMemory, Double expNodeDisk, Double expNodeMemory, Fixture f) {
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/FleetControllerClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/content/FleetControllerClusterTest.java
index 10bb00168bb..dedf344c546 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/content/FleetControllerClusterTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/content/FleetControllerClusterTest.java
@@ -1,6 +1,7 @@
// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.content;
+import com.yahoo.config.model.api.ModelContext;
import com.yahoo.config.model.application.provider.BaseDeployLogger;
import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.model.deploy.TestProperties;
@@ -22,12 +23,15 @@ public class FleetControllerClusterTest {
new TestProperties().enableFeedBlockInDistributor(enableFeedBlockInDistributor)).build();
MockRoot root = new MockRoot("", deployState);
var clusterElement = new ModelElement(doc.getDocumentElement());
+ ModelContext.FeatureFlags featureFlags = new TestProperties();
return new ClusterControllerConfig.Builder("storage",
clusterElement,
new ClusterResourceLimits.Builder(enableFeedBlockInDistributor,
false,
false,
- new BaseDeployLogger())
+ new BaseDeployLogger(),
+ featureFlags.resourceLimitDisk(),
+ featureFlags.resourceLimitMemory())
.build(clusterElement).getClusterControllerLimits())
.build(root.getDeployState(), root, clusterElement.getXml());
}