Add disk threshold settings validation
This commit adds cross-settings validation for the low/high/flood stage disk watermark settings. This validation was enabled by the introduction of multiple settings validation. Relates #25600
This commit is contained in:
parent
794257c421
commit
bc22c1c286
|
@ -21,6 +21,7 @@ package org.elasticsearch.gradle.test
|
||||||
import org.apache.tools.ant.DefaultLogger
|
import org.apache.tools.ant.DefaultLogger
|
||||||
import org.apache.tools.ant.taskdefs.condition.Os
|
import org.apache.tools.ant.taskdefs.condition.Os
|
||||||
import org.elasticsearch.gradle.LoggedExec
|
import org.elasticsearch.gradle.LoggedExec
|
||||||
|
import org.elasticsearch.gradle.Version
|
||||||
import org.elasticsearch.gradle.VersionProperties
|
import org.elasticsearch.gradle.VersionProperties
|
||||||
import org.elasticsearch.gradle.plugin.PluginBuildPlugin
|
import org.elasticsearch.gradle.plugin.PluginBuildPlugin
|
||||||
import org.elasticsearch.gradle.plugin.PluginPropertiesExtension
|
import org.elasticsearch.gradle.plugin.PluginPropertiesExtension
|
||||||
|
@ -312,6 +313,9 @@ class ClusterFormationTasks {
|
||||||
// Default the watermarks to absurdly low to prevent the tests from failing on nodes without enough disk space
|
// Default the watermarks to absurdly low to prevent the tests from failing on nodes without enough disk space
|
||||||
esConfig['cluster.routing.allocation.disk.watermark.low'] = '1b'
|
esConfig['cluster.routing.allocation.disk.watermark.low'] = '1b'
|
||||||
esConfig['cluster.routing.allocation.disk.watermark.high'] = '1b'
|
esConfig['cluster.routing.allocation.disk.watermark.high'] = '1b'
|
||||||
|
if (Version.fromString(node.nodeVersion).major >= 6) {
|
||||||
|
esConfig['cluster.routing.allocation.disk.watermark.floodstage'] = '1b'
|
||||||
|
}
|
||||||
esConfig.putAll(node.config.settings)
|
esConfig.putAll(node.config.settings)
|
||||||
|
|
||||||
Task writeConfig = project.tasks.create(name: name, type: DefaultTask, dependsOn: setup)
|
Task writeConfig = project.tasks.create(name: name, type: DefaultTask, dependsOn: setup)
|
||||||
|
|
|
@ -27,6 +27,11 @@ import org.elasticsearch.common.unit.ByteSizeValue;
|
||||||
import org.elasticsearch.common.unit.RatioValue;
|
import org.elasticsearch.common.unit.RatioValue;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A container to keep settings for disk thresholds up to date with cluster setting changes.
|
* A container to keep settings for disk thresholds up to date with cluster setting changes.
|
||||||
*/
|
*/
|
||||||
|
@ -37,14 +42,17 @@ public class DiskThresholdSettings {
|
||||||
public static final Setting<String> CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING =
|
public static final Setting<String> CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING =
|
||||||
new Setting<>("cluster.routing.allocation.disk.watermark.low", "85%",
|
new Setting<>("cluster.routing.allocation.disk.watermark.low", "85%",
|
||||||
(s) -> validWatermarkSetting(s, "cluster.routing.allocation.disk.watermark.low"),
|
(s) -> validWatermarkSetting(s, "cluster.routing.allocation.disk.watermark.low"),
|
||||||
|
new LowDiskWatermarkValidator(),
|
||||||
Setting.Property.Dynamic, Setting.Property.NodeScope);
|
Setting.Property.Dynamic, Setting.Property.NodeScope);
|
||||||
public static final Setting<String> CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING =
|
public static final Setting<String> CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING =
|
||||||
new Setting<>("cluster.routing.allocation.disk.watermark.high", "90%",
|
new Setting<>("cluster.routing.allocation.disk.watermark.high", "90%",
|
||||||
(s) -> validWatermarkSetting(s, "cluster.routing.allocation.disk.watermark.high"),
|
(s) -> validWatermarkSetting(s, "cluster.routing.allocation.disk.watermark.high"),
|
||||||
|
new HighDiskWatermarkValidator(),
|
||||||
Setting.Property.Dynamic, Setting.Property.NodeScope);
|
Setting.Property.Dynamic, Setting.Property.NodeScope);
|
||||||
public static final Setting<String> CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING =
|
public static final Setting<String> CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING =
|
||||||
new Setting<>("cluster.routing.allocation.disk.watermark.floodstage", "95%",
|
new Setting<>("cluster.routing.allocation.disk.watermark.floodstage", "95%",
|
||||||
(s) -> validWatermarkSetting(s, "cluster.routing.allocation.disk.watermark.floodstage"),
|
(s) -> validWatermarkSetting(s, "cluster.routing.allocation.disk.watermark.floodstage"),
|
||||||
|
new FloodStageValidator(),
|
||||||
Setting.Property.Dynamic, Setting.Property.NodeScope);
|
Setting.Property.Dynamic, Setting.Property.NodeScope);
|
||||||
public static final Setting<Boolean> CLUSTER_ROUTING_ALLOCATION_INCLUDE_RELOCATIONS_SETTING =
|
public static final Setting<Boolean> CLUSTER_ROUTING_ALLOCATION_INCLUDE_RELOCATIONS_SETTING =
|
||||||
Setting.boolSetting("cluster.routing.allocation.disk.include_relocations", true,
|
Setting.boolSetting("cluster.routing.allocation.disk.include_relocations", true,
|
||||||
|
@ -84,6 +92,116 @@ public class DiskThresholdSettings {
|
||||||
clusterSettings.addSettingsUpdateConsumer(CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING, this::setEnabled);
|
clusterSettings.addSettingsUpdateConsumer(CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING, this::setEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final class LowDiskWatermarkValidator implements Setting.Validator<String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate(String value, Map<Setting<String>, String> settings) {
|
||||||
|
final String highWatermarkRaw = settings.get(CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING);
|
||||||
|
final String floodStageRaw = settings.get(CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING);
|
||||||
|
doValidate(value, highWatermarkRaw, floodStageRaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Setting<String>> settings() {
|
||||||
|
return Arrays.asList(
|
||||||
|
CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING,
|
||||||
|
CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING)
|
||||||
|
.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class HighDiskWatermarkValidator implements Setting.Validator<String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate(String value, Map<Setting<String>, String> settings) {
|
||||||
|
final String lowWatermarkRaw = settings.get(CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING);
|
||||||
|
final String floodStageRaw = settings.get(CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING);
|
||||||
|
doValidate(lowWatermarkRaw, value, floodStageRaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Setting<String>> settings() {
|
||||||
|
return Arrays.asList(
|
||||||
|
CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING,
|
||||||
|
CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING)
|
||||||
|
.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class FloodStageValidator implements Setting.Validator<String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate(String value, Map<Setting<String>, String> settings) {
|
||||||
|
final String lowWatermarkRaw = settings.get(CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING);
|
||||||
|
final String highWatermarkRaw = settings.get(CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING);
|
||||||
|
doValidate(lowWatermarkRaw, highWatermarkRaw, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Setting<String>> settings() {
|
||||||
|
return Arrays.asList(
|
||||||
|
CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING,
|
||||||
|
CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING)
|
||||||
|
.iterator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void doValidate(String low, String high, String flood) {
|
||||||
|
try {
|
||||||
|
doValidateAsPercentage(low, high, flood);
|
||||||
|
return; // early return so that we do not try to parse as bytes
|
||||||
|
} catch (final ElasticsearchParseException e) {
|
||||||
|
// swallow as we are now going to try to parse as bytes
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
doValidateAsBytes(low, high, flood);
|
||||||
|
} catch (final ElasticsearchParseException e) {
|
||||||
|
final String message = String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"unable to consistently parse [%s=%s], [%s=%s], and [%s=%s] as percentage or bytes",
|
||||||
|
CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(),
|
||||||
|
low,
|
||||||
|
CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(),
|
||||||
|
high,
|
||||||
|
CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(),
|
||||||
|
flood);
|
||||||
|
throw new IllegalArgumentException(message, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void doValidateAsPercentage(final String low, final String high, final String flood) {
|
||||||
|
final double lowWatermarkThreshold = thresholdPercentageFromWatermark(low, false);
|
||||||
|
final double highWatermarkThreshold = thresholdPercentageFromWatermark(high, false);
|
||||||
|
final double floodThreshold = thresholdPercentageFromWatermark(flood, false);
|
||||||
|
if (lowWatermarkThreshold > highWatermarkThreshold) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"low disk watermark [" + low + "] more than high disk watermark [" + high + "]");
|
||||||
|
}
|
||||||
|
if (highWatermarkThreshold > floodThreshold) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"high disk watermark [" + high + "] more than flood stage disk watermark [" + flood + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void doValidateAsBytes(final String low, final String high, final String flood) {
|
||||||
|
final ByteSizeValue lowWatermarkBytes =
|
||||||
|
thresholdBytesFromWatermark(low, CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), false);
|
||||||
|
final ByteSizeValue highWatermarkBytes =
|
||||||
|
thresholdBytesFromWatermark(high, CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), false);
|
||||||
|
final ByteSizeValue floodStageBytes =
|
||||||
|
thresholdBytesFromWatermark(flood, CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), false);
|
||||||
|
if (lowWatermarkBytes.getBytes() < highWatermarkBytes.getBytes()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"low disk watermark [" + low + "] less than high disk watermark [" + high + "]");
|
||||||
|
}
|
||||||
|
if (highWatermarkBytes.getBytes() < floodStageBytes.getBytes()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"high disk watermark [" + high + "] less than flood stage disk watermark [" + flood + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setIncludeRelocations(boolean includeRelocations) {
|
private void setIncludeRelocations(boolean includeRelocations) {
|
||||||
this.includeRelocations = includeRelocations;
|
this.includeRelocations = includeRelocations;
|
||||||
}
|
}
|
||||||
|
@ -178,13 +296,28 @@ public class DiskThresholdSettings {
|
||||||
* Attempts to parse the watermark into a percentage, returning 100.0% if
|
* Attempts to parse the watermark into a percentage, returning 100.0% if
|
||||||
* it cannot be parsed.
|
* it cannot be parsed.
|
||||||
*/
|
*/
|
||||||
private double thresholdPercentageFromWatermark(String watermark) {
|
private static double thresholdPercentageFromWatermark(String watermark) {
|
||||||
|
return thresholdPercentageFromWatermark(watermark, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to parse the watermark into a percentage, returning 100.0% if it can not be parsed and the specified lenient parameter is
|
||||||
|
* true, otherwise throwing an {@link ElasticsearchParseException}.
|
||||||
|
*
|
||||||
|
* @param watermark the watermark to parse as a percentage
|
||||||
|
* @param lenient true if lenient parsing should be applied
|
||||||
|
* @return the parsed percentage
|
||||||
|
*/
|
||||||
|
private static double thresholdPercentageFromWatermark(String watermark, boolean lenient) {
|
||||||
try {
|
try {
|
||||||
return RatioValue.parseRatioValue(watermark).getAsPercent();
|
return RatioValue.parseRatioValue(watermark).getAsPercent();
|
||||||
} catch (ElasticsearchParseException ex) {
|
} catch (ElasticsearchParseException ex) {
|
||||||
// NOTE: this is not end-user leniency, since up above we check that it's a valid byte or percentage, and then store the two
|
// NOTE: this is not end-user leniency, since up above we check that it's a valid byte or percentage, and then store the two
|
||||||
// cases separately
|
// cases separately
|
||||||
return 100.0;
|
if (lenient) {
|
||||||
|
return 100.0;
|
||||||
|
}
|
||||||
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,13 +325,29 @@ public class DiskThresholdSettings {
|
||||||
* Attempts to parse the watermark into a {@link ByteSizeValue}, returning
|
* Attempts to parse the watermark into a {@link ByteSizeValue}, returning
|
||||||
* a ByteSizeValue of 0 bytes if the value cannot be parsed.
|
* a ByteSizeValue of 0 bytes if the value cannot be parsed.
|
||||||
*/
|
*/
|
||||||
private ByteSizeValue thresholdBytesFromWatermark(String watermark, String settingName) {
|
private static ByteSizeValue thresholdBytesFromWatermark(String watermark, String settingName) {
|
||||||
|
return thresholdBytesFromWatermark(watermark, settingName, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to parse the watermark into a {@link ByteSizeValue}, returning zero bytes if it can not be parsed and the specified lenient
|
||||||
|
* parameter is true, otherwise throwing an {@link ElasticsearchParseException}.
|
||||||
|
*
|
||||||
|
* @param watermark the watermark to parse as a byte size
|
||||||
|
* @param settingName the name of the setting
|
||||||
|
* @param lenient true if lenient parsing should be applied
|
||||||
|
* @return the parsed byte size value
|
||||||
|
*/
|
||||||
|
private static ByteSizeValue thresholdBytesFromWatermark(String watermark, String settingName, boolean lenient) {
|
||||||
try {
|
try {
|
||||||
return ByteSizeValue.parseBytesSizeValue(watermark, settingName);
|
return ByteSizeValue.parseBytesSizeValue(watermark, settingName);
|
||||||
} catch (ElasticsearchParseException ex) {
|
} catch (ElasticsearchParseException ex) {
|
||||||
// NOTE: this is not end-user leniency, since up above we check that it's a valid byte or percentage, and then store the two
|
// NOTE: this is not end-user leniency, since up above we check that it's a valid byte or percentage, and then store the two
|
||||||
// cases separately
|
// cases separately
|
||||||
return ByteSizeValue.parseBytesSizeValue("0b", settingName);
|
if (lenient) {
|
||||||
|
return ByteSizeValue.parseBytesSizeValue("0b", settingName);
|
||||||
|
}
|
||||||
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,12 @@ import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.hasToString;
|
||||||
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
|
|
||||||
public class DiskThresholdSettingsTests extends ESTestCase {
|
public class DiskThresholdSettingsTests extends ESTestCase {
|
||||||
|
|
||||||
public void testDefaults() {
|
public void testDefaults() {
|
||||||
|
@ -47,18 +53,154 @@ public class DiskThresholdSettingsTests extends ESTestCase {
|
||||||
Settings newSettings = Settings.builder()
|
Settings newSettings = Settings.builder()
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), false)
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), false)
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_INCLUDE_RELOCATIONS_SETTING.getKey(), false)
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_INCLUDE_RELOCATIONS_SETTING.getKey(), false)
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "70%")
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "500mb")
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "500mb")
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1000mb")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "250mb")
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_REROUTE_INTERVAL_SETTING.getKey(), "30s")
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_REROUTE_INTERVAL_SETTING.getKey(), "30s")
|
||||||
.build();
|
.build();
|
||||||
nss.applySettings(newSettings);
|
nss.applySettings(newSettings);
|
||||||
|
|
||||||
assertEquals(ByteSizeValue.parseBytesSizeValue("0b", "test"), diskThresholdSettings.getFreeBytesThresholdHigh());
|
assertEquals(ByteSizeValue.parseBytesSizeValue("500mb", "test"), diskThresholdSettings.getFreeBytesThresholdHigh());
|
||||||
assertEquals(30.0D, diskThresholdSettings.getFreeDiskThresholdHigh(), 0.0D);
|
assertEquals(0.0D, diskThresholdSettings.getFreeDiskThresholdHigh(), 0.0D);
|
||||||
assertEquals(ByteSizeValue.parseBytesSizeValue("500mb", "test"), diskThresholdSettings.getFreeBytesThresholdLow());
|
assertEquals(ByteSizeValue.parseBytesSizeValue("1000mb", "test"), diskThresholdSettings.getFreeBytesThresholdLow());
|
||||||
assertEquals(0.0D, diskThresholdSettings.getFreeDiskThresholdLow(), 0.0D);
|
assertEquals(0.0D, diskThresholdSettings.getFreeDiskThresholdLow(), 0.0D);
|
||||||
|
assertEquals(ByteSizeValue.parseBytesSizeValue("250mb", "test"), diskThresholdSettings.getFreeBytesThresholdFloodStage());
|
||||||
|
assertEquals(0.0D, diskThresholdSettings.getFreeDiskThresholdFloodStage(), 0.0D);
|
||||||
assertEquals(30L, diskThresholdSettings.getRerouteInterval().seconds());
|
assertEquals(30L, diskThresholdSettings.getRerouteInterval().seconds());
|
||||||
assertFalse(diskThresholdSettings.isEnabled());
|
assertFalse(diskThresholdSettings.isEnabled());
|
||||||
assertFalse(diskThresholdSettings.includeRelocations());
|
assertFalse(diskThresholdSettings.includeRelocations());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testInvalidConstruction() {
|
||||||
|
final Settings settings = Settings.builder()
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "90%")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "80%")
|
||||||
|
.build();
|
||||||
|
final ClusterSettings clusterSettings = new ClusterSettings(settings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
|
||||||
|
final IllegalArgumentException e =
|
||||||
|
expectThrows(IllegalArgumentException.class, () -> new DiskThresholdSettings(settings, clusterSettings));
|
||||||
|
assertThat(e, hasToString(containsString("low disk watermark [90%] more than high disk watermark [80%]")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvalidLowHighPercentageUpdate() {
|
||||||
|
final ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
|
||||||
|
new DiskThresholdSettings(Settings.EMPTY, clusterSettings); // this has the effect of registering the settings updater
|
||||||
|
|
||||||
|
final Settings newSettings = Settings.builder()
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "90%")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "80%")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> clusterSettings.applySettings(newSettings));
|
||||||
|
final String expected = "illegal value can't update [cluster.routing.allocation.disk.watermark.low] from [85%] to [90%]";
|
||||||
|
assertThat(e, hasToString(containsString(expected)));
|
||||||
|
assertNotNull(e.getCause());
|
||||||
|
assertThat(e.getCause(), instanceOf(IllegalArgumentException.class));
|
||||||
|
final IllegalArgumentException cause = (IllegalArgumentException) e.getCause();
|
||||||
|
assertThat(cause, hasToString(containsString("low disk watermark [90%] more than high disk watermark [80%]")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvalidHighFloodPercentageUpdate() {
|
||||||
|
final ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
|
||||||
|
new DiskThresholdSettings(Settings.EMPTY, clusterSettings); // this has the effect of registering the settings updater
|
||||||
|
|
||||||
|
final Settings newSettings = Settings.builder()
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "50%")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "60%")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "55%")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> clusterSettings.applySettings(newSettings));
|
||||||
|
final String expected = "illegal value can't update [cluster.routing.allocation.disk.watermark.low] from [85%] to [50%]";
|
||||||
|
assertThat(e, hasToString(containsString(expected)));
|
||||||
|
assertNotNull(e.getCause());
|
||||||
|
assertThat(e.getCause(), instanceOf(IllegalArgumentException.class));
|
||||||
|
final IllegalArgumentException cause = (IllegalArgumentException) e.getCause();
|
||||||
|
assertThat(cause, hasToString(containsString("high disk watermark [60%] more than flood stage disk watermark [55%]")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvalidLowHighBytesUpdate() {
|
||||||
|
final ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
|
||||||
|
new DiskThresholdSettings(Settings.EMPTY, clusterSettings); // this has the effect of registering the settings updater
|
||||||
|
|
||||||
|
final Settings newSettings = Settings.builder()
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "500m")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1000m")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "250m")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> clusterSettings.applySettings(newSettings));
|
||||||
|
final String expected = "illegal value can't update [cluster.routing.allocation.disk.watermark.low] from [85%] to [500m]";
|
||||||
|
assertThat(e, hasToString(containsString(expected)));
|
||||||
|
assertNotNull(e.getCause());
|
||||||
|
assertThat(e.getCause(), instanceOf(IllegalArgumentException.class));
|
||||||
|
final IllegalArgumentException cause = (IllegalArgumentException) e.getCause();
|
||||||
|
assertThat(cause, hasToString(containsString("low disk watermark [500m] less than high disk watermark [1000m]")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvalidHighFloodBytesUpdate() {
|
||||||
|
final ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
|
||||||
|
new DiskThresholdSettings(Settings.EMPTY, clusterSettings); // this has the effect of registering the settings updater
|
||||||
|
|
||||||
|
final Settings newSettings = Settings.builder()
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "500m")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1000m")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "750m")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> clusterSettings.applySettings(newSettings));
|
||||||
|
final String expected = "illegal value can't update [cluster.routing.allocation.disk.watermark.low] from [85%] to [500m]";
|
||||||
|
assertThat(e, hasToString(containsString(expected)));
|
||||||
|
assertNotNull(e.getCause());
|
||||||
|
assertThat(e.getCause(), instanceOf(IllegalArgumentException.class));
|
||||||
|
final IllegalArgumentException cause = (IllegalArgumentException) e.getCause();
|
||||||
|
assertThat(cause, hasToString(containsString("low disk watermark [500m] less than high disk watermark [1000m]")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIncompatibleThresholdUpdate() {
|
||||||
|
final ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
|
||||||
|
new DiskThresholdSettings(Settings.EMPTY, clusterSettings); // this has the effect of registering the settings updater
|
||||||
|
|
||||||
|
final Settings newSettings = Settings.builder()
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "90%")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1000m")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "95%")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> clusterSettings.applySettings(newSettings));
|
||||||
|
final String expected = "illegal value can't update [cluster.routing.allocation.disk.watermark.low] from [85%] to [90%]";
|
||||||
|
assertThat(e, hasToString(containsString(expected)));
|
||||||
|
assertNotNull(e.getCause());
|
||||||
|
assertThat(e.getCause(), instanceOf(IllegalArgumentException.class));
|
||||||
|
final IllegalArgumentException cause = (IllegalArgumentException) e.getCause();
|
||||||
|
final String incompatibleExpected = String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"unable to consistently parse [%s=%s], [%s=%s], and [%s=%s] as percentage or bytes",
|
||||||
|
DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(),
|
||||||
|
"90%",
|
||||||
|
DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(),
|
||||||
|
"1000m",
|
||||||
|
DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(),
|
||||||
|
"95%");
|
||||||
|
assertThat(cause, hasToString(containsString(incompatibleExpected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvalidHighDiskThreshold() {
|
||||||
|
final ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
|
||||||
|
new DiskThresholdSettings(Settings.EMPTY, clusterSettings); // this has the effect of registering the settings updater
|
||||||
|
|
||||||
|
final Settings newSettings = Settings.builder()
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "75%")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> clusterSettings.applySettings(newSettings));
|
||||||
|
final String expected = "illegal value can't update [cluster.routing.allocation.disk.watermark.high] from [90%] to [75%]";
|
||||||
|
assertThat(e, hasToString(containsString(expected)));
|
||||||
|
assertNotNull(e.getCause());
|
||||||
|
assertNotNull(e.getCause());
|
||||||
|
assertThat(e.getCause(), instanceOf(IllegalArgumentException.class));
|
||||||
|
final IllegalArgumentException cause = (IllegalArgumentException) e.getCause();
|
||||||
|
assertThat(cause, hasToString(containsString("low disk watermark [85%] more than high disk watermark [75%]")));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,8 @@ public class DiskThresholdDeciderTests extends ESAllocationTestCase {
|
||||||
Settings diskSettings = Settings.builder()
|
Settings diskSettings = Settings.builder()
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), 0.7)
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), 0.7)
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), 0.8).build();
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), 0.8)
|
||||||
|
.build();
|
||||||
|
|
||||||
ImmutableOpenMap.Builder<String, DiskUsage> usagesBuilder = ImmutableOpenMap.builder();
|
ImmutableOpenMap.Builder<String, DiskUsage> usagesBuilder = ImmutableOpenMap.builder();
|
||||||
usagesBuilder.put("node1", new DiskUsage("node1", "node1", "/dev/null", 100, 10)); // 90% used
|
usagesBuilder.put("node1", new DiskUsage("node1", "node1", "/dev/null", 100, 10)); // 90% used
|
||||||
|
@ -179,7 +180,8 @@ public class DiskThresholdDeciderTests extends ESAllocationTestCase {
|
||||||
diskSettings = Settings.builder()
|
diskSettings = Settings.builder()
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "60%")
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "60%")
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), 0.7).build();
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), 0.7)
|
||||||
|
.build();
|
||||||
|
|
||||||
deciders = new AllocationDeciders(Settings.EMPTY,
|
deciders = new AllocationDeciders(Settings.EMPTY,
|
||||||
new HashSet<>(Arrays.asList(
|
new HashSet<>(Arrays.asList(
|
||||||
|
@ -209,7 +211,8 @@ public class DiskThresholdDeciderTests extends ESAllocationTestCase {
|
||||||
diskSettings = Settings.builder()
|
diskSettings = Settings.builder()
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), 0.5)
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), 0.5)
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), 0.6).build();
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), 0.6)
|
||||||
|
.build();
|
||||||
|
|
||||||
deciders = new AllocationDeciders(Settings.EMPTY,
|
deciders = new AllocationDeciders(Settings.EMPTY,
|
||||||
new HashSet<>(Arrays.asList(
|
new HashSet<>(Arrays.asList(
|
||||||
|
@ -259,7 +262,9 @@ public class DiskThresholdDeciderTests extends ESAllocationTestCase {
|
||||||
Settings diskSettings = Settings.builder()
|
Settings diskSettings = Settings.builder()
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "30b")
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "30b")
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "9b").build();
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "9b")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "5b")
|
||||||
|
.build();
|
||||||
|
|
||||||
ImmutableOpenMap.Builder<String, DiskUsage> usagesBuilder = ImmutableOpenMap.builder();
|
ImmutableOpenMap.Builder<String, DiskUsage> usagesBuilder = ImmutableOpenMap.builder();
|
||||||
usagesBuilder.put("node1", new DiskUsage("node1", "n1", "/dev/null", 100, 10)); // 90% used
|
usagesBuilder.put("node1", new DiskUsage("node1", "n1", "/dev/null", 100, 10)); // 90% used
|
||||||
|
@ -397,7 +402,9 @@ public class DiskThresholdDeciderTests extends ESAllocationTestCase {
|
||||||
diskSettings = Settings.builder()
|
diskSettings = Settings.builder()
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "40b")
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "40b")
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "30b").build();
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "30b")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "20b")
|
||||||
|
.build();
|
||||||
|
|
||||||
deciders = new AllocationDeciders(Settings.EMPTY,
|
deciders = new AllocationDeciders(Settings.EMPTY,
|
||||||
new HashSet<>(Arrays.asList(
|
new HashSet<>(Arrays.asList(
|
||||||
|
@ -427,7 +434,9 @@ public class DiskThresholdDeciderTests extends ESAllocationTestCase {
|
||||||
diskSettings = Settings.builder()
|
diskSettings = Settings.builder()
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED_SETTING.getKey(), true)
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "50b")
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "50b")
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "40b").build();
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "40b")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "30b")
|
||||||
|
.build();
|
||||||
|
|
||||||
deciders = new AllocationDeciders(Settings.EMPTY,
|
deciders = new AllocationDeciders(Settings.EMPTY,
|
||||||
new HashSet<>(Arrays.asList(
|
new HashSet<>(Arrays.asList(
|
||||||
|
|
|
@ -71,10 +71,13 @@ public class MockDiskUsagesIT extends ESIntegTestCase {
|
||||||
cis.setN2Usage(nodes.get(1), new DiskUsage(nodes.get(1), "n2", "/dev/null", 100, 50));
|
cis.setN2Usage(nodes.get(1), new DiskUsage(nodes.get(1), "n2", "/dev/null", 100, 50));
|
||||||
cis.setN3Usage(nodes.get(2), new DiskUsage(nodes.get(2), "n3", "/dev/null", 100, 50));
|
cis.setN3Usage(nodes.get(2), new DiskUsage(nodes.get(2), "n3", "/dev/null", 100, 50));
|
||||||
|
|
||||||
|
final boolean watermarkBytes = randomBoolean(); // we have to consistently use bytes or percentage for the disk watermark settings
|
||||||
client().admin().cluster().prepareUpdateSettings().setTransientSettings(Settings.builder()
|
client().admin().cluster().prepareUpdateSettings().setTransientSettings(Settings.builder()
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), randomFrom("20b", "80%"))
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), watermarkBytes ? "20b" : "80%")
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), randomFrom("10b", "90%"))
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), watermarkBytes ? "10b" : "90%")
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), randomFrom("0b", "100%"))
|
.put(
|
||||||
|
DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(),
|
||||||
|
watermarkBytes ? "0b" : "100%")
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_REROUTE_INTERVAL_SETTING.getKey(), "1ms")).get();
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_REROUTE_INTERVAL_SETTING.getKey(), "1ms")).get();
|
||||||
// Create an index with 10 shards so we can check allocation for it
|
// Create an index with 10 shards so we can check allocation for it
|
||||||
prepareCreate("test").setSettings(Settings.builder()
|
prepareCreate("test").setSettings(Settings.builder()
|
||||||
|
|
|
@ -29,14 +29,21 @@ file or updated dynamically on a live cluster with the
|
||||||
the node.
|
the node.
|
||||||
|
|
||||||
`cluster.routing.allocation.disk.watermark.floodstage`::
|
`cluster.routing.allocation.disk.watermark.floodstage`::
|
||||||
+
|
|
||||||
--
|
Controls the flood stage watermark. It defaults to 95%, meaning ES enforces
|
||||||
Controls the floodstage watermark. It defaults to 95%, meaning ES enforces a read-only
|
a read-only index block (`index.blocks.read_only_allow_delete`) on every
|
||||||
index block (`index.blocks.read_only_allow_delete`) on every index that has
|
index that has one or more shards allocated on the node that has at least
|
||||||
one or more shards allocated on the node that has at least one disk exceeding the floodstage.
|
one disk exceeding the flood stage. This is a last resort to prevent nodes
|
||||||
This is a last resort to prevent nodes from running out of disk space.
|
from running out of disk space. The index block must be released manually
|
||||||
The index block must be released manually once there is enough disk space available
|
once there is enough disk space available to allow indexing operations to
|
||||||
to allow indexing operations to continue.
|
continue.
|
||||||
|
|
||||||
|
NOTE: You can not mix the usage of percentage values and byte values within
|
||||||
|
these settings. Either all are set to percentage values, or all are set to byte
|
||||||
|
values. This is so that we can we validate that the settings are internally
|
||||||
|
consistent (that is, the low disk threshold is not more than the high disk
|
||||||
|
threshold, and the high disk threshold is not more than the flood stage
|
||||||
|
threshold).
|
||||||
|
|
||||||
An example of resetting the read-only index block on the `twitter` index:
|
An example of resetting the read-only index block on the `twitter` index:
|
||||||
|
|
||||||
|
@ -72,18 +79,16 @@ free disk space. This can be confusing, since it flips the meaning of high and
|
||||||
low. For example, it makes sense to set the low watermark to 10gb and the high
|
low. For example, it makes sense to set the low watermark to 10gb and the high
|
||||||
watermark to 5gb, but not the other way around.
|
watermark to 5gb, but not the other way around.
|
||||||
|
|
||||||
|
An example of updating the low watermark to at least 100 gigabytes free, a high
|
||||||
An example of updating the low watermark to no more than 80% of the disk size,
|
watermark of at least 50 gigabytes free, and a flood stage watermark of 10
|
||||||
a high watermark of at least 50 gigabytes free, and a floodstage watermark of
|
gigabytes free, and updating the information about the cluster every minute:
|
||||||
10 gigabytes free, and updating the information about the cluster every
|
|
||||||
minute:
|
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
PUT _cluster/settings
|
PUT _cluster/settings
|
||||||
{
|
{
|
||||||
"transient": {
|
"transient": {
|
||||||
"cluster.routing.allocation.disk.watermark.low": "80%",
|
"cluster.routing.allocation.disk.watermark.low": "100gb",
|
||||||
"cluster.routing.allocation.disk.watermark.high": "50gb",
|
"cluster.routing.allocation.disk.watermark.high": "50gb",
|
||||||
"cluster.routing.allocation.disk.watermark.floodstage": "10gb",
|
"cluster.routing.allocation.disk.watermark.floodstage": "10gb",
|
||||||
"cluster.info.update.interval": "1m"
|
"cluster.info.update.interval": "1m"
|
||||||
|
|
|
@ -1721,6 +1721,7 @@ public abstract class ESIntegTestCase extends ESTestCase {
|
||||||
// from failing on nodes without enough disk space
|
// from failing on nodes without enough disk space
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1b")
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1b")
|
||||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1b")
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1b")
|
||||||
|
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "1b")
|
||||||
.put(ScriptService.SCRIPT_MAX_COMPILATIONS_PER_MINUTE.getKey(), 2048)
|
.put(ScriptService.SCRIPT_MAX_COMPILATIONS_PER_MINUTE.getKey(), 2048)
|
||||||
// by default we never cache below 10k docs in a segment,
|
// by default we never cache below 10k docs in a segment,
|
||||||
// bypass this limit so that caching gets some testing in
|
// bypass this limit so that caching gets some testing in
|
||||||
|
|
|
@ -331,6 +331,7 @@ public final class InternalTestCluster extends TestCluster {
|
||||||
// from failing on nodes without enough disk space
|
// from failing on nodes without enough disk space
|
||||||
builder.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1b");
|
builder.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1b");
|
||||||
builder.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1b");
|
builder.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1b");
|
||||||
|
builder.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "1b");
|
||||||
// Some tests make use of scripting quite a bit, so increase the limit for integration tests
|
// Some tests make use of scripting quite a bit, so increase the limit for integration tests
|
||||||
builder.put(ScriptService.SCRIPT_MAX_COMPILATIONS_PER_MINUTE.getKey(), 1000);
|
builder.put(ScriptService.SCRIPT_MAX_COMPILATIONS_PER_MINUTE.getKey(), 1000);
|
||||||
if (TEST_NIGHTLY) {
|
if (TEST_NIGHTLY) {
|
||||||
|
|
Loading…
Reference in New Issue