Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ setup:
- is_true: nodes.$node_id.roles
# the roles output is sorted
- match: { nodes.$node_id.roles.0: "data" }
- match: { nodes.$node_id.roles.1: "ingest" }
- match: { nodes.$node_id.roles.2: "master" }
- match: { nodes.$node_id.roles.3: "remote_cluster_client" }

- match: { nodes.$node_id.roles.1: "data_cold" }
- match: { nodes.$node_id.roles.2: "data_content" }
- match: { nodes.$node_id.roles.3: "data_frozen" }
- match: { nodes.$node_id.roles.4: "data_hot" }
- match: { nodes.$node_id.roles.5: "data_warm" }
- match: { nodes.$node_id.roles.6: "ingest" }
- match: { nodes.$node_id.roles.7: "master" }
- match: { nodes.$node_id.roles.8: "remote_cluster_client" }
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ public void testNodeCounts() {
internalCluster().startNode();
Map<String, Integer> expectedCounts = new HashMap<>();
expectedCounts.put(DiscoveryNodeRole.DATA_ROLE.roleName(), 1);
expectedCounts.put(DiscoveryNodeRole.DATA_CONTENT_NODE_ROLE.roleName(), 1);
expectedCounts.put(DiscoveryNodeRole.DATA_COLD_NODE_ROLE.roleName(), 1);
expectedCounts.put(DiscoveryNodeRole.DATA_FROZEN_NODE_ROLE.roleName(), 1);
expectedCounts.put(DiscoveryNodeRole.DATA_HOT_NODE_ROLE.roleName(), 1);
expectedCounts.put(DiscoveryNodeRole.DATA_WARM_NODE_ROLE.roleName(), 1);
expectedCounts.put(DiscoveryNodeRole.MASTER_ROLE.roleName(), 1);
expectedCounts.put(DiscoveryNodeRole.INGEST_ROLE.roleName(), 1);
expectedCounts.put(DiscoveryNodeRole.REMOTE_CLUSTER_CLIENT_ROLE.roleName(), 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void testPickingUpChangesInDiscoveryNode() {
String nodeName = internalCluster().startNode(nonDataNode());

TransportClient client = (TransportClient) internalCluster().client(nodeName);
assertThat(client.connectedNodes().get(0).isDataNode(), equalTo(false));
assertThat(client.connectedNodes().get(0).canContainData(), equalTo(false));

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.elasticsearch.Version;
import org.elasticsearch.cluster.node.DiscoveryNodeRole;
import org.elasticsearch.common.CheckedConsumer;
import org.elasticsearch.common.collect.Set;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.gateway.PersistedClusterStateService;
Expand All @@ -22,9 +23,6 @@
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import static org.elasticsearch.test.NodeRoles.nonDataNode;
Expand Down Expand Up @@ -62,9 +60,7 @@ public void testStartFailureOnDataForNonDataNode() throws Exception {
internalCluster().restartRandomDataNode(new InternalTestCluster.RestartCallback() {
@Override
public Settings onNodeStopped(String nodeName) {
return NodeRoles.removeRoles(Collections.unmodifiableSet(
new HashSet<>(Arrays.asList(DiscoveryNodeRole.DATA_ROLE, DiscoveryNodeRole.MASTER_ROLE))
));
return NodeRoles.removeRoles(nonDataNode(), Set.of(DiscoveryNodeRole.MASTER_ROLE));
}
}));
if (writeDanglingIndices) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import org.elasticsearch.test.ESIntegTestCase;
import org.hamcrest.Matcher;

import static org.elasticsearch.test.NodeRoles.nonDataNode;
import static org.elasticsearch.test.NodeRoles.nonMasterNode;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;

Expand Down Expand Up @@ -45,7 +47,7 @@ public void testRepurpose() throws Exception {
final Settings dataNodeDataPathSettings = internalCluster().dataPathSettings(dataNode);

// put some unknown role here to make sure the tool does not bark when encountering an unknown role
final Settings noMasterNoDataSettings = Settings.builder().putList("node.roles", "unknown_role").build();
final Settings noMasterNoDataSettings = nonMasterNode(nonDataNode());

final Settings noMasterNoDataSettingsForMasterNode = Settings.builder()
.put(noMasterNoDataSettings)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ public void testCorruptionOnNetworkLayerFinalizingRecovery() throws ExecutionExc
NodesStatsResponse nodeStats = client().admin().cluster().prepareNodesStats().get();
List<NodeStats> dataNodeStats = new ArrayList<>();
for (NodeStats stat : nodeStats.getNodes()) {
if (stat.getNode().isDataNode()) {
if (stat.getNode().canContainData()) {
dataNodeStats.add(stat);
}
}
Expand Down Expand Up @@ -384,7 +384,7 @@ public void testCorruptionOnNetworkLayer() throws ExecutionException, Interrupte
NodesStatsResponse nodeStats = client().admin().cluster().prepareNodesStats().get();
List<NodeStats> dataNodeStats = new ArrayList<>();
for (NodeStats stat : nodeStats.getNodes()) {
if (stat.getNode().isDataNode()) {
if (stat.getNode().canContainData()) {
dataNodeStats.add(stat);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void testRetryDueToExceptionOnNetworkLayer() throws ExecutionException, I
int numDocs = scaledRandomIntBetween(100, 1000);
Client client = internalCluster().coordOnlyNodeClient();
NodesStatsResponse nodeStats = client().admin().cluster().prepareNodesStats().get();
NodeStats unluckyNode = randomFrom(nodeStats.getNodes().stream().filter((s) -> s.getNode().isDataNode())
NodeStats unluckyNode = randomFrom(nodeStats.getNodes().stream().filter((s) -> s.getNode().canContainData())
.collect(Collectors.toList()));
assertAcked(client().admin().indices().prepareCreate("index").setSettings(Settings.builder()
.put("index.number_of_replicas", 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ public void testLimitsRequestSize() {
NodesStatsResponse nodeStats = client().admin().cluster().prepareNodesStats().get();
List<NodeStats> dataNodeStats = new ArrayList<>();
for (NodeStats stat : nodeStats.getNodes()) {
if (stat.getNode().isDataNode()) {
if (stat.getNode().canContainData()) {
dataNodeStats.add(stat);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public void testCloseWhileRelocatingShards() throws Exception {
(MockTransportService) internalCluster().getInstance(TransportService.class, targetNode);

for (DiscoveryNode node : state.getNodes()) {
if (node.isDataNode() && node.getName().equals(targetNode) == false) {
if (node.canContainData() && node.getName().equals(targetNode) == false) {
final TransportService sourceTransportService = internalCluster().getInstance(TransportService.class, node.getName());
targetTransportService.addSendBehavior(sourceTransportService, sendBehavior);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void testCancelRecoveryAndResume() throws Exception {
NodesStatsResponse nodeStats = client().admin().cluster().prepareNodesStats().get();
List<NodeStats> dataNodeStats = new ArrayList<>();
for (NodeStats stat : nodeStats.getNodes()) {
if (stat.getNode().isDataNode()) {
if (stat.getNode().canContainData()) {
dataNodeStats.add(stat);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void testCancel() throws Exception {
if (randomBoolean()) {
remoteCluster.ensureAtLeastNumDataNodes(3);
List<String> remoteDataNodes = StreamSupport.stream(remoteCluster.clusterService().state().nodes().spliterator(), false)
.filter(DiscoveryNode::isDataNode)
.filter(DiscoveryNode::canContainData)
.map(DiscoveryNode::getName)
.collect(Collectors.toList());
assertThat(remoteDataNodes.size(), Matchers.greaterThanOrEqualTo(3));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public void clusterChanged(ClusterChangedEvent event) {

// Refresh if a data node was added
for (DiscoveryNode addedNode : event.nodesDelta().addedNodes()) {
if (addedNode.isDataNode()) {
if (addedNode.canContainData()) {
refreshAsync(new PlainActionFuture<>());
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.xcontent.ToXContentFragment;
Expand Down Expand Up @@ -47,7 +46,7 @@ public class DiscoveryNode implements Writeable, ToXContentFragment {

public static boolean nodeRequiresLocalStorage(Settings settings) {
boolean localStorageEnable = Node.NODE_LOCAL_STORAGE_SETTING.get(settings);
if (localStorageEnable == false && (isDataNode(settings) || isMasterNode(settings))) {
if (localStorageEnable == false && (canContainData(settings) || isMasterNode(settings))) {
// TODO: make this a proper setting validation logic, requiring multi-settings validation
throw new IllegalArgumentException("storage can not be disabled for master and data nodes");
}
Expand All @@ -74,21 +73,28 @@ public static boolean isMasterNode(Settings settings) {
}

/**
* Due to the way that plugins may not be available when settings are being initialized,
* not all roles may be available from a static/initializing context such as a {@link Setting}
* default value function. In that case, be warned that this may not include all plugin roles.
* Check if the given settings are indicative of having the top-level data role.
*
* Note that if you want to test for whether or not the given settings are indicative of any role that can contain data, you should use
* {@link #canContainData(Settings)}.
*
* @param settings the settings
* @return true if the given settings are indicative of having the top-level data role, otherwise false
*/
public static boolean isDataNode(final Settings settings) {
return getRolesFromSettings(settings).stream().anyMatch(DiscoveryNodeRole::canContainData);
public static boolean hasDataRole(final Settings settings) {
return hasRole(settings, DiscoveryNodeRole.DATA_ROLE);
}

/**
* Allows determining the "data" property without the need to load plugins, but does this purely based on
* naming conventions. Prefer using {@link #isDataNode(Settings)} if possible.
* Check if the given settings are indicative of any role that can contain data.
*
* Note that if you want to test for exactly the data role, you should use {@link #hasDataRole(Settings)}.
*
* @param settings the settings
* @return true if the given settings are indicative of having any role that can contain data, otherwise false
*/
public static boolean isDataNodeBasedOnNamingConvention(final Settings settings) {
return DiscoveryNode.hasRole(settings, DiscoveryNodeRole.DATA_ROLE) ||
settings.getAsList("node.roles").stream().anyMatch(DiscoveryNodeRole::isDataRoleBasedOnNamingConvention);
public static boolean canContainData(final Settings settings) {
return getRolesFromSettings(settings).stream().anyMatch(DiscoveryNodeRole::canContainData);
}

public static boolean isIngestNode(final Settings settings) {
Expand Down Expand Up @@ -388,7 +394,7 @@ public Map<String, String> getAttributes() {
/**
* Should this node hold data (shards) or not.
*/
public boolean isDataNode() {
public boolean canContainData() {
return roles.stream().anyMatch(DiscoveryNodeRole::canContainData);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
package org.elasticsearch.cluster.node;

import org.elasticsearch.Version;
import org.elasticsearch.common.collect.Set;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.transport.RemoteClusterService;

import java.util.Arrays;
Expand Down Expand Up @@ -78,8 +80,6 @@ protected DiscoveryNodeRole(final String roleName, final String roleNameAbbrevia

protected DiscoveryNodeRole(final String roleName, final String roleNameAbbreviation, final boolean canContainData) {
this(true, roleName, roleNameAbbreviation, canContainData);
assert canContainData == isDataRoleBasedOnNamingConvention(roleName) :
"Role '" + roleName + "' not compliant to data role naming convention";
}

private DiscoveryNodeRole(
Expand Down Expand Up @@ -150,13 +150,126 @@ public Setting<Boolean> legacySetting() {

};

/**
* Allows determining the "data" property without the need to load plugins, but does this purely based on
* naming conventions.
*/
static boolean isDataRoleBasedOnNamingConvention(String role) {
return role.equals("data") || role.startsWith("data_");
}
public static DiscoveryNodeRole DATA_CONTENT_NODE_ROLE = new DiscoveryNodeRole("data_content", "s", true) {
@Override
public boolean isEnabledByDefault(final Settings settings) {
return DiscoveryNode.hasRole(settings, DiscoveryNodeRole.DATA_ROLE);
}

@Override
public Setting<Boolean> legacySetting() {
// we do not register these settings, they're not intended to be used externally, only for proper defaults
return Setting.boolSetting(
"node.data_content",
settings ->
// Don't use DiscoveryNode#isDataNode(Settings) here, as it is called before all plugins are initialized
Boolean.toString(DiscoveryNode.hasRole(settings, DiscoveryNodeRole.DATA_ROLE)),
Setting.Property.Deprecated,
Setting.Property.NodeScope
);
}

@Override
public DiscoveryNodeRole getCompatibilityRole(Version nodeVersion) {
return nodeVersion.before(Version.V_7_10_0) ? DiscoveryNodeRole.DATA_ROLE : this;
}
};

public static DiscoveryNodeRole DATA_HOT_NODE_ROLE = new DiscoveryNodeRole("data_hot", "h", true) {
@Override
public boolean isEnabledByDefault(final Settings settings) {
return DiscoveryNode.hasRole(settings, DiscoveryNodeRole.DATA_ROLE);
}

@Override
public Setting<Boolean> legacySetting() {
// we do not register these settings, they're not intended to be used externally, only for proper defaults
return Setting.boolSetting(
"node.data_hot",
settings ->
// Don't use DiscoveryNode#isDataNode(Settings) here, as it is called before all plugins are initialized
Boolean.toString(DiscoveryNode.hasRole(settings, DiscoveryNodeRole.DATA_ROLE)),
Setting.Property.Deprecated,
Setting.Property.NodeScope
);
}

@Override
public DiscoveryNodeRole getCompatibilityRole(Version nodeVersion) {
return nodeVersion.before(Version.V_7_10_0) ? DiscoveryNodeRole.DATA_ROLE : this;
}
};

public static DiscoveryNodeRole DATA_WARM_NODE_ROLE = new DiscoveryNodeRole("data_warm", "w", true) {
@Override
public boolean isEnabledByDefault(final Settings settings) {
return DiscoveryNode.hasRole(settings, DiscoveryNodeRole.DATA_ROLE);
}

@Override
public Setting<Boolean> legacySetting() {
// we do not register these settings, they're not intended to be used externally, only for proper defaults
return Setting.boolSetting(
"node.data_warm",
settings ->
// Don't use DiscoveryNode#isDataNode(Settings) here, as it is called before all plugins are initialized
Boolean.toString(DiscoveryNode.hasRole(settings, DiscoveryNodeRole.DATA_ROLE)),
Setting.Property.Deprecated,
Setting.Property.NodeScope
);
}

@Override
public DiscoveryNodeRole getCompatibilityRole(Version nodeVersion) {
return nodeVersion.before(Version.V_7_10_0) ? DiscoveryNodeRole.DATA_ROLE : this;
}
};

public static DiscoveryNodeRole DATA_COLD_NODE_ROLE = new DiscoveryNodeRole("data_cold", "c", true) {
@Override
public boolean isEnabledByDefault(final Settings settings) {
return DiscoveryNode.hasRole(settings, DiscoveryNodeRole.DATA_ROLE);
}

@Override
public Setting<Boolean> legacySetting() {
// we do not register these settings, they're not intended to be used externally, only for proper defaults
return Setting.boolSetting(
"node.data_cold",
settings ->
// Don't use DiscoveryNode#isDataNode(Settings) here, as it is called before all plugins are initialized
Boolean.toString(DiscoveryNode.hasRole(settings, DiscoveryNodeRole.DATA_ROLE)),
Setting.Property.Deprecated,
Setting.Property.NodeScope
);
}

@Override
public DiscoveryNodeRole getCompatibilityRole(Version nodeVersion) {
return nodeVersion.before(Version.V_7_10_0) ? DiscoveryNodeRole.DATA_ROLE : this;
}
};

public static DiscoveryNodeRole DATA_FROZEN_NODE_ROLE = new DiscoveryNodeRole("data_frozen", "f", true) {
@Override
public boolean isEnabledByDefault(final Settings settings) {
return DiscoveryNode.hasRole(settings, DiscoveryNodeRole.DATA_ROLE);
}

@Override
public Setting<Boolean> legacySetting() {
// we do not register these settings, they're not intended to be used externally, only for proper defaults
return Setting.boolSetting(
"node.data_frozen",
settings ->
// Don't use DiscoveryNode#isDataNode(Settings) here, as it is called before all plugins are initialized
Boolean.toString(DiscoveryNode.hasRole(settings, DiscoveryNodeRole.DATA_ROLE)),
Setting.Property.Deprecated,
Setting.Property.NodeScope
);
}

};

/**
* Represents the role for an ingest node.
Expand Down Expand Up @@ -202,8 +315,18 @@ public Setting<Boolean> legacySetting() {
/**
* The built-in node roles.
*/
public static SortedSet<DiscoveryNodeRole> BUILT_IN_ROLES = Collections.unmodifiableSortedSet(
new TreeSet<>(Arrays.asList(DATA_ROLE, INGEST_ROLE, MASTER_ROLE, REMOTE_CLUSTER_CLIENT_ROLE)));
public static final SortedSet<DiscoveryNodeRole> BUILT_IN_ROLES =
Set.of(
DATA_ROLE,
INGEST_ROLE,
MASTER_ROLE,
REMOTE_CLUSTER_CLIENT_ROLE,
DATA_CONTENT_NODE_ROLE,
DATA_HOT_NODE_ROLE,
DATA_WARM_NODE_ROLE,
DATA_COLD_NODE_ROLE,
DATA_FROZEN_NODE_ROLE
).stream().collect(Sets.toUnmodifiableSortedSet());

/**
* The version that {@link #REMOTE_CLUSTER_CLIENT_ROLE} is introduced. Nodes before this version do not have that role even
Expand Down
Loading