diff --git a/CHANGELOG.md b/CHANGELOG.md index 82c289f41fbfc..886fad43a066b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased 2.x] ### Added - Add GeoTile and GeoHash Grid aggregations on GeoShapes. ([#5589](https://github.com/opensearch-project/OpenSearch/pull/5589)) +- Disallow multiple data paths for search nodes ([#6427](https://github.com/opensearch-project/OpenSearch/pull/6427)) ### Dependencies diff --git a/server/src/main/java/org/opensearch/bootstrap/BootstrapChecks.java b/server/src/main/java/org/opensearch/bootstrap/BootstrapChecks.java index 5d595dc1abedf..c27c149947444 100644 --- a/server/src/main/java/org/opensearch/bootstrap/BootstrapChecks.java +++ b/server/src/main/java/org/opensearch/bootstrap/BootstrapChecks.java @@ -38,15 +38,18 @@ import org.apache.lucene.util.Constants; import org.opensearch.bootstrap.jvm.DenyJvmVersionsParser; import org.opensearch.cluster.coordination.ClusterBootstrapService; +import org.opensearch.cluster.node.DiscoveryNodeRole; import org.opensearch.common.SuppressForbidden; import org.opensearch.common.io.PathUtils; import org.opensearch.common.settings.Setting; import org.opensearch.common.transport.BoundTransportAddress; import org.opensearch.common.transport.TransportAddress; import org.opensearch.discovery.DiscoveryModule; +import org.opensearch.env.Environment; import org.opensearch.index.IndexModule; import org.opensearch.monitor.jvm.JvmInfo; import org.opensearch.monitor.process.ProcessProbe; +import org.opensearch.node.NodeRoleSettings; import org.opensearch.node.NodeValidationException; import java.io.BufferedReader; @@ -228,6 +231,7 @@ static List checks() { checks.add(new JavaVersionCheck()); checks.add(new AllPermissionCheck()); checks.add(new DiscoveryConfiguredCheck()); + checks.add(new MultipleDataPathCheck()); return Collections.unmodifiableList(checks); } @@ -751,4 +755,25 @@ public BootstrapCheckResult check(BootstrapContext context) { ); } } + + /** + * Bootstrap check that if a search node contains multiple data paths + */ + static class MultipleDataPathCheck implements BootstrapCheck { + + @Override + public BootstrapCheckResult check(BootstrapContext context) { + if (NodeRoleSettings.NODE_ROLES_SETTING.get(context.settings()).contains(DiscoveryNodeRole.SEARCH_ROLE) + && Environment.PATH_DATA_SETTING.get(context.settings()).size() > 1) { + return BootstrapCheckResult.failure("Multiple data paths are not allowed for search nodes"); + } + return BootstrapCheckResult.success(); + } + + @Override + public final boolean alwaysEnforce() { + return true; + } + + } } diff --git a/server/src/test/java/org/opensearch/bootstrap/BootstrapChecksTests.java b/server/src/test/java/org/opensearch/bootstrap/BootstrapChecksTests.java index 8edb204ac0402..15aacd25b30b1 100644 --- a/server/src/test/java/org/opensearch/bootstrap/BootstrapChecksTests.java +++ b/server/src/test/java/org/opensearch/bootstrap/BootstrapChecksTests.java @@ -36,19 +36,24 @@ import org.apache.lucene.util.Constants; import org.opensearch.cluster.coordination.ClusterBootstrapService; import org.opensearch.cluster.metadata.Metadata; +import org.opensearch.cluster.node.DiscoveryNodeRole; import org.opensearch.common.CheckedConsumer; +import org.opensearch.common.io.PathUtils; import org.opensearch.common.settings.Settings; import org.opensearch.common.transport.BoundTransportAddress; import org.opensearch.common.transport.TransportAddress; import org.opensearch.discovery.DiscoveryModule; import org.opensearch.discovery.SettingsBasedSeedHostsProvider; +import org.opensearch.env.Environment; import org.opensearch.monitor.jvm.JvmInfo; +import org.opensearch.node.NodeRoleSettings; import org.opensearch.node.NodeValidationException; import org.opensearch.test.AbstractBootstrapCheckTestCase; import org.hamcrest.Matcher; import java.lang.Runtime.Version; import java.net.InetAddress; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -774,4 +779,41 @@ Version getVersion() { version.set(Runtime.version()); BootstrapChecks.check(emptyContext, true, Collections.singletonList(check)); } + + public void testMultipleDataPathsForSearchNodeCheck() { + Path path = PathUtils.get(createTempDir().toString()); + String[] paths = new String[] { path.resolve("a").toString(), path.resolve("b").toString() }; + + final NodeValidationException e = expectThrows( + NodeValidationException.class, + () -> performDataPathsCheck(paths, DiscoveryNodeRole.SEARCH_ROLE.roleName()) + ); + assertThat(e.getMessage(), containsString("Multiple data paths are not allowed for search nodes")); + } + + public void testMultipleDataPathsForDataNodeCheck() throws NodeValidationException { + Path path = PathUtils.get(createTempDir().toString()); + String[] paths = new String[] { path.resolve("a").toString(), path.resolve("b").toString() }; + + performDataPathsCheck(paths, DiscoveryNodeRole.DATA_ROLE.roleName()); + } + + public void testSingleDataPathForSearchNodeCheck() throws NodeValidationException { + Path path = PathUtils.get(createTempDir().toString()); + String[] paths = new String[] { path.resolve("a").toString() }; + + performDataPathsCheck(paths, DiscoveryNodeRole.SEARCH_ROLE.roleName()); + } + + private void performDataPathsCheck(String[] paths, String roleName) throws NodeValidationException { + final BootstrapContext context = createTestContext( + Settings.builder() + .putList(NodeRoleSettings.NODE_ROLES_SETTING.getKey(), Collections.singletonList(roleName)) + .putList(Environment.PATH_DATA_SETTING.getKey(), paths) + .build(), + Metadata.EMPTY_METADATA + ); + final List checks = Collections.singletonList(new BootstrapChecks.MultipleDataPathCheck()); + BootstrapChecks.check(context, true, checks); + } }