Zen2: Rename tombstones to exclusions (#36226)
Renames the withdrawal / tombstones APIs to voting configuration exclusions.
This commit is contained in:
parent
5d6602120f
commit
03d0ea91ef
|
@ -91,7 +91,8 @@ public class Zen2RestApiIT extends ESNetty4IntegTestCase {
|
||||||
public void doAfterNodes(int n, Client client) throws IOException {
|
public void doAfterNodes(int n, Client client) throws IOException {
|
||||||
ensureGreen("test");
|
ensureGreen("test");
|
||||||
Response response =
|
Response response =
|
||||||
restClient.performRequest(new Request("POST", "/_cluster/withdrawn_votes/" + internalCluster().getNodeNames()[n]));
|
restClient.performRequest(new Request("POST", "/_cluster/voting_config_exclusions/" +
|
||||||
|
internalCluster().getNodeNames()[n]));
|
||||||
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +112,7 @@ public class Zen2RestApiIT extends ESNetty4IntegTestCase {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
Response deleteResponse = restClient.performRequest(new Request("DELETE", "/_cluster/withdrawn_votes"));
|
Response deleteResponse = restClient.performRequest(new Request("DELETE", "/_cluster/voting_config_exclusions"));
|
||||||
assertThat(deleteResponse.getStatusLine().getStatusCode(), is(200));
|
assertThat(deleteResponse.getStatusLine().getStatusCode(), is(200));
|
||||||
|
|
||||||
ClusterHealthResponse clusterHealthResponse = client(viaNode).admin().cluster().prepareHealth()
|
ClusterHealthResponse clusterHealthResponse = client(viaNode).admin().cluster().prepareHealth()
|
||||||
|
@ -135,10 +136,11 @@ public class Zen2RestApiIT extends ESNetty4IntegTestCase {
|
||||||
public void testClearVotingTombstonesNotWaitingForRemoval() throws Exception {
|
public void testClearVotingTombstonesNotWaitingForRemoval() throws Exception {
|
||||||
List<String> nodes = internalCluster().startNodes(3);
|
List<String> nodes = internalCluster().startNodes(3);
|
||||||
RestClient restClient = getRestClient();
|
RestClient restClient = getRestClient();
|
||||||
Response response = restClient.performRequest(new Request("POST", "/_cluster/withdrawn_votes/" + nodes.get(2)));
|
Response response = restClient.performRequest(new Request("POST", "/_cluster/voting_config_exclusions/" + nodes.get(2)));
|
||||||
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
||||||
assertThat(response.getEntity().getContentLength(), is(0L));
|
assertThat(response.getEntity().getContentLength(), is(0L));
|
||||||
Response deleteResponse = restClient.performRequest(new Request("DELETE", "/_cluster/withdrawn_votes/?wait_for_removal=false"));
|
Response deleteResponse = restClient.performRequest(
|
||||||
|
new Request("DELETE", "/_cluster/voting_config_exclusions/?wait_for_removal=false"));
|
||||||
assertThat(deleteResponse.getStatusLine().getStatusCode(), is(200));
|
assertThat(deleteResponse.getStatusLine().getStatusCode(), is(200));
|
||||||
assertThat(deleteResponse.getEntity().getContentLength(), is(0L));
|
assertThat(deleteResponse.getEntity().getContentLength(), is(0L));
|
||||||
}
|
}
|
||||||
|
@ -147,11 +149,11 @@ public class Zen2RestApiIT extends ESNetty4IntegTestCase {
|
||||||
List<String> nodes = internalCluster().startNodes(3);
|
List<String> nodes = internalCluster().startNodes(3);
|
||||||
RestClient restClient = getRestClient();
|
RestClient restClient = getRestClient();
|
||||||
String nodeToWithdraw = nodes.get(randomIntBetween(0, 2));
|
String nodeToWithdraw = nodes.get(randomIntBetween(0, 2));
|
||||||
Response response = restClient.performRequest(new Request("POST", "/_cluster/withdrawn_votes/" + nodeToWithdraw));
|
Response response = restClient.performRequest(new Request("POST", "/_cluster/voting_config_exclusions/" + nodeToWithdraw));
|
||||||
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
||||||
assertThat(response.getEntity().getContentLength(), is(0L));
|
assertThat(response.getEntity().getContentLength(), is(0L));
|
||||||
internalCluster().stopRandomNode(InternalTestCluster.nameFilter(nodeToWithdraw));
|
internalCluster().stopRandomNode(InternalTestCluster.nameFilter(nodeToWithdraw));
|
||||||
Response deleteResponse = restClient.performRequest(new Request("DELETE", "/_cluster/withdrawn_votes"));
|
Response deleteResponse = restClient.performRequest(new Request("DELETE", "/_cluster/voting_config_exclusions"));
|
||||||
assertThat(deleteResponse.getStatusLine().getStatusCode(), is(200));
|
assertThat(deleteResponse.getStatusLine().getStatusCode(), is(200));
|
||||||
assertThat(deleteResponse.getEntity().getContentLength(), is(0L));
|
assertThat(deleteResponse.getEntity().getContentLength(), is(0L));
|
||||||
}
|
}
|
||||||
|
@ -160,13 +162,13 @@ public class Zen2RestApiIT extends ESNetty4IntegTestCase {
|
||||||
internalCluster().startNodes(3);
|
internalCluster().startNodes(3);
|
||||||
RestClient restClient = getRestClient();
|
RestClient restClient = getRestClient();
|
||||||
try {
|
try {
|
||||||
restClient.performRequest(new Request("POST", "/_cluster/withdrawn_votes/invalid"));
|
restClient.performRequest(new Request("POST", "/_cluster/voting_config_exclusions/invalid"));
|
||||||
fail("Invalid node name should throw.");
|
fail("Invalid node name should throw.");
|
||||||
} catch (ResponseException e) {
|
} catch (ResponseException e) {
|
||||||
assertThat(e.getResponse().getStatusLine().getStatusCode(), is(400));
|
assertThat(e.getResponse().getStatusLine().getStatusCode(), is(400));
|
||||||
assertThat(
|
assertThat(
|
||||||
e.getCause().getMessage(),
|
e.getCause().getMessage(),
|
||||||
Matchers.containsString("add voting tombstones request for [invalid] matched no master-eligible nodes")
|
Matchers.containsString("add voting config exclusions request for [invalid] matched no master-eligible nodes")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ import org.elasticsearch.action.admin.cluster.bootstrap.BootstrapClusterAction;
|
||||||
import org.elasticsearch.action.admin.cluster.bootstrap.GetDiscoveredNodesAction;
|
import org.elasticsearch.action.admin.cluster.bootstrap.GetDiscoveredNodesAction;
|
||||||
import org.elasticsearch.action.admin.cluster.bootstrap.TransportBootstrapClusterAction;
|
import org.elasticsearch.action.admin.cluster.bootstrap.TransportBootstrapClusterAction;
|
||||||
import org.elasticsearch.action.admin.cluster.bootstrap.TransportGetDiscoveredNodesAction;
|
import org.elasticsearch.action.admin.cluster.bootstrap.TransportGetDiscoveredNodesAction;
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.AddVotingTombstonesAction;
|
import org.elasticsearch.action.admin.cluster.configuration.AddVotingConfigExclusionsAction;
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingTombstonesAction;
|
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingConfigExclusionsAction;
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.TransportAddVotingTombstonesAction;
|
import org.elasticsearch.action.admin.cluster.configuration.TransportAddVotingConfigExclusionsAction;
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.TransportClearVotingTombstonesAction;
|
import org.elasticsearch.action.admin.cluster.configuration.TransportClearVotingConfigExclusionsAction;
|
||||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthAction;
|
import org.elasticsearch.action.admin.cluster.health.ClusterHealthAction;
|
||||||
import org.elasticsearch.action.admin.cluster.health.TransportClusterHealthAction;
|
import org.elasticsearch.action.admin.cluster.health.TransportClusterHealthAction;
|
||||||
import org.elasticsearch.action.admin.cluster.node.hotthreads.NodesHotThreadsAction;
|
import org.elasticsearch.action.admin.cluster.node.hotthreads.NodesHotThreadsAction;
|
||||||
|
@ -225,7 +225,7 @@ import org.elasticsearch.rest.RestHandler;
|
||||||
import org.elasticsearch.rest.action.RestFieldCapabilitiesAction;
|
import org.elasticsearch.rest.action.RestFieldCapabilitiesAction;
|
||||||
import org.elasticsearch.rest.action.RestMainAction;
|
import org.elasticsearch.rest.action.RestMainAction;
|
||||||
import org.elasticsearch.rest.action.admin.cluster.RestCancelTasksAction;
|
import org.elasticsearch.rest.action.admin.cluster.RestCancelTasksAction;
|
||||||
import org.elasticsearch.rest.action.admin.cluster.RestClearVotingTombstonesAction;
|
import org.elasticsearch.rest.action.admin.cluster.RestClearVotingConfigExclusionsAction;
|
||||||
import org.elasticsearch.rest.action.admin.cluster.RestClusterAllocationExplainAction;
|
import org.elasticsearch.rest.action.admin.cluster.RestClusterAllocationExplainAction;
|
||||||
import org.elasticsearch.rest.action.admin.cluster.RestClusterGetSettingsAction;
|
import org.elasticsearch.rest.action.admin.cluster.RestClusterGetSettingsAction;
|
||||||
import org.elasticsearch.rest.action.admin.cluster.RestClusterHealthAction;
|
import org.elasticsearch.rest.action.admin.cluster.RestClusterHealthAction;
|
||||||
|
@ -255,7 +255,7 @@ import org.elasticsearch.rest.action.admin.cluster.RestRemoteClusterInfoAction;
|
||||||
import org.elasticsearch.rest.action.admin.cluster.RestRestoreSnapshotAction;
|
import org.elasticsearch.rest.action.admin.cluster.RestRestoreSnapshotAction;
|
||||||
import org.elasticsearch.rest.action.admin.cluster.RestSnapshotsStatusAction;
|
import org.elasticsearch.rest.action.admin.cluster.RestSnapshotsStatusAction;
|
||||||
import org.elasticsearch.rest.action.admin.cluster.RestVerifyRepositoryAction;
|
import org.elasticsearch.rest.action.admin.cluster.RestVerifyRepositoryAction;
|
||||||
import org.elasticsearch.rest.action.admin.cluster.RestAddVotingTombstonesAction;
|
import org.elasticsearch.rest.action.admin.cluster.RestAddVotingConfigExclusionAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestAnalyzeAction;
|
import org.elasticsearch.rest.action.admin.indices.RestAnalyzeAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestClearIndicesCacheAction;
|
import org.elasticsearch.rest.action.admin.indices.RestClearIndicesCacheAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestCloseIndexAction;
|
import org.elasticsearch.rest.action.admin.indices.RestCloseIndexAction;
|
||||||
|
@ -435,8 +435,8 @@ public class ActionModule extends AbstractModule {
|
||||||
|
|
||||||
actions.register(GetDiscoveredNodesAction.INSTANCE, TransportGetDiscoveredNodesAction.class);
|
actions.register(GetDiscoveredNodesAction.INSTANCE, TransportGetDiscoveredNodesAction.class);
|
||||||
actions.register(BootstrapClusterAction.INSTANCE, TransportBootstrapClusterAction.class);
|
actions.register(BootstrapClusterAction.INSTANCE, TransportBootstrapClusterAction.class);
|
||||||
actions.register(AddVotingTombstonesAction.INSTANCE, TransportAddVotingTombstonesAction.class);
|
actions.register(AddVotingConfigExclusionsAction.INSTANCE, TransportAddVotingConfigExclusionsAction.class);
|
||||||
actions.register(ClearVotingTombstonesAction.INSTANCE, TransportClearVotingTombstonesAction.class);
|
actions.register(ClearVotingConfigExclusionsAction.INSTANCE, TransportClearVotingConfigExclusionsAction.class);
|
||||||
actions.register(ClusterAllocationExplainAction.INSTANCE, TransportClusterAllocationExplainAction.class);
|
actions.register(ClusterAllocationExplainAction.INSTANCE, TransportClusterAllocationExplainAction.class);
|
||||||
actions.register(ClusterStatsAction.INSTANCE, TransportClusterStatsAction.class);
|
actions.register(ClusterStatsAction.INSTANCE, TransportClusterStatsAction.class);
|
||||||
actions.register(ClusterStateAction.INSTANCE, TransportClusterStateAction.class);
|
actions.register(ClusterStateAction.INSTANCE, TransportClusterStateAction.class);
|
||||||
|
@ -545,8 +545,8 @@ public class ActionModule extends AbstractModule {
|
||||||
catActions.add((AbstractCatAction) a);
|
catActions.add((AbstractCatAction) a);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
registerHandler.accept(new RestAddVotingTombstonesAction(settings, restController));
|
registerHandler.accept(new RestAddVotingConfigExclusionAction(settings, restController));
|
||||||
registerHandler.accept(new RestClearVotingTombstonesAction(settings, restController));
|
registerHandler.accept(new RestClearVotingConfigExclusionsAction(settings, restController));
|
||||||
registerHandler.accept(new RestMainAction(settings, restController));
|
registerHandler.accept(new RestMainAction(settings, restController));
|
||||||
registerHandler.accept(new RestNodesInfoAction(settings, restController, settingsFilter));
|
registerHandler.accept(new RestNodesInfoAction(settings, restController, settingsFilter));
|
||||||
registerHandler.accept(new RestRemoteClusterInfoAction(settings, restController));
|
registerHandler.accept(new RestRemoteClusterInfoAction(settings, restController));
|
||||||
|
|
|
@ -21,21 +21,21 @@ package org.elasticsearch.action.admin.cluster.configuration;
|
||||||
import org.elasticsearch.action.Action;
|
import org.elasticsearch.action.Action;
|
||||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||||
|
|
||||||
public class AddVotingTombstonesAction extends Action<AddVotingTombstonesResponse> {
|
public class AddVotingConfigExclusionsAction extends Action<AddVotingConfigExclusionsResponse> {
|
||||||
public static final AddVotingTombstonesAction INSTANCE = new AddVotingTombstonesAction();
|
public static final AddVotingConfigExclusionsAction INSTANCE = new AddVotingConfigExclusionsAction();
|
||||||
public static final String NAME = "cluster:admin/voting/add_tombstones";
|
public static final String NAME = "cluster:admin/voting_config/add_exclusions";
|
||||||
|
|
||||||
private AddVotingTombstonesAction() {
|
private AddVotingConfigExclusionsAction() {
|
||||||
super(NAME);
|
super(NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AddVotingTombstonesResponse newResponse() {
|
public AddVotingConfigExclusionsResponse newResponse() {
|
||||||
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
|
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Reader<AddVotingTombstonesResponse> getResponseReader() {
|
public Reader<AddVotingConfigExclusionsResponse> getResponseReader() {
|
||||||
return AddVotingTombstonesResponse::new;
|
return AddVotingConfigExclusionsResponse::new;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@ package org.elasticsearch.action.admin.cluster.configuration;
|
||||||
import org.elasticsearch.action.ActionRequestValidationException;
|
import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
import org.elasticsearch.action.support.master.MasterNodeRequest;
|
import org.elasticsearch.action.support.master.MasterNodeRequest;
|
||||||
import org.elasticsearch.cluster.ClusterState;
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
@ -34,29 +34,29 @@ import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A request to add voting tombstones for certain master-eligible nodes, and wait for these nodes to be removed from the voting
|
* A request to add voting config exclusions for certain master-eligible nodes, and wait for these nodes to be removed from the voting
|
||||||
* configuration.
|
* configuration.
|
||||||
*/
|
*/
|
||||||
public class AddVotingTombstonesRequest extends MasterNodeRequest<AddVotingTombstonesRequest> {
|
public class AddVotingConfigExclusionsRequest extends MasterNodeRequest<AddVotingConfigExclusionsRequest> {
|
||||||
private final String[] nodeDescriptions;
|
private final String[] nodeDescriptions;
|
||||||
private final TimeValue timeout;
|
private final TimeValue timeout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a request to add voting tombstones for master-eligible nodes matching the given descriptions, and wait for a default 30
|
* Construct a request to add voting config exclusions for master-eligible nodes matching the given descriptions, and wait for a
|
||||||
* seconds for these nodes to be removed from the voting configuration.
|
* default 30 seconds for these exclusions to take effect, removing the nodes from the voting configuration.
|
||||||
* @param nodeDescriptions Descriptions of the nodes to add - see {@link DiscoveryNodes#resolveNodes(String...)}
|
* @param nodeDescriptions Descriptions of the nodes to add - see {@link DiscoveryNodes#resolveNodes(String...)}
|
||||||
*/
|
*/
|
||||||
public AddVotingTombstonesRequest(String[] nodeDescriptions) {
|
public AddVotingConfigExclusionsRequest(String[] nodeDescriptions) {
|
||||||
this(nodeDescriptions, TimeValue.timeValueSeconds(30));
|
this(nodeDescriptions, TimeValue.timeValueSeconds(30));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a request to add voting tombstones for master-eligible nodes matching the given descriptions, and wait for these nodes to
|
* Construct a request to add voting config exclusions for master-eligible nodes matching the given descriptions, and wait for these
|
||||||
* be removed from the voting configuration.
|
* nodes to be removed from the voting configuration.
|
||||||
* @param nodeDescriptions Descriptions of the nodes whose tombstones to add - see {@link DiscoveryNodes#resolveNodes(String...)}.
|
* @param nodeDescriptions Descriptions of the nodes whose exclusions to add - see {@link DiscoveryNodes#resolveNodes(String...)}.
|
||||||
* @param timeout How long to wait for the nodes to be removed from the voting configuration.
|
* @param timeout How long to wait for the added exclusions to take effect and be removed from the voting configuration.
|
||||||
*/
|
*/
|
||||||
public AddVotingTombstonesRequest(String[] nodeDescriptions, TimeValue timeout) {
|
public AddVotingConfigExclusionsRequest(String[] nodeDescriptions, TimeValue timeout) {
|
||||||
if (timeout.compareTo(TimeValue.ZERO) < 0) {
|
if (timeout.compareTo(TimeValue.ZERO) < 0) {
|
||||||
throw new IllegalArgumentException("timeout [" + timeout + "] must be non-negative");
|
throw new IllegalArgumentException("timeout [" + timeout + "] must be non-negative");
|
||||||
}
|
}
|
||||||
|
@ -64,50 +64,50 @@ public class AddVotingTombstonesRequest extends MasterNodeRequest<AddVotingTombs
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AddVotingTombstonesRequest(StreamInput in) throws IOException {
|
public AddVotingConfigExclusionsRequest(StreamInput in) throws IOException {
|
||||||
super(in);
|
super(in);
|
||||||
nodeDescriptions = in.readStringArray();
|
nodeDescriptions = in.readStringArray();
|
||||||
timeout = in.readTimeValue();
|
timeout = in.readTimeValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<VotingTombstone> resolveVotingTombstones(ClusterState currentState) {
|
Set<VotingConfigExclusion> resolveVotingConfigExclusions(ClusterState currentState) {
|
||||||
final DiscoveryNodes allNodes = currentState.nodes();
|
final DiscoveryNodes allNodes = currentState.nodes();
|
||||||
final Set<VotingTombstone> resolvedNodes = Arrays.stream(allNodes.resolveNodes(nodeDescriptions))
|
final Set<VotingConfigExclusion> resolvedNodes = Arrays.stream(allNodes.resolveNodes(nodeDescriptions))
|
||||||
.map(allNodes::get).filter(DiscoveryNode::isMasterNode).map(VotingTombstone::new).collect(Collectors.toSet());
|
.map(allNodes::get).filter(DiscoveryNode::isMasterNode).map(VotingConfigExclusion::new).collect(Collectors.toSet());
|
||||||
|
|
||||||
if (resolvedNodes.isEmpty()) {
|
if (resolvedNodes.isEmpty()) {
|
||||||
throw new IllegalArgumentException("add voting tombstones request for " + Arrays.asList(nodeDescriptions)
|
throw new IllegalArgumentException("add voting config exclusions request for " + Arrays.asList(nodeDescriptions)
|
||||||
+ " matched no master-eligible nodes");
|
+ " matched no master-eligible nodes");
|
||||||
}
|
}
|
||||||
|
|
||||||
resolvedNodes.removeIf(n -> currentState.getVotingTombstones().contains(n));
|
resolvedNodes.removeIf(n -> currentState.getVotingConfigExclusions().contains(n));
|
||||||
return resolvedNodes;
|
return resolvedNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<VotingTombstone> resolveVotingTombstonesAndCheckMaximum(ClusterState currentState, int maxTombstoneCount,
|
Set<VotingConfigExclusion> resolveVotingConfigExclusionsAndCheckMaximum(ClusterState currentState, int maxExclusionsCount,
|
||||||
String maximumSettingKey) {
|
String maximumSettingKey) {
|
||||||
final Set<VotingTombstone> resolvedNodes = resolveVotingTombstones(currentState);
|
final Set<VotingConfigExclusion> resolvedExclusions = resolveVotingConfigExclusions(currentState);
|
||||||
|
|
||||||
final int oldTombstoneCount = currentState.getVotingTombstones().size();
|
final int oldExclusionsCount = currentState.getVotingConfigExclusions().size();
|
||||||
final int newTombstoneCount = resolvedNodes.size();
|
final int newExclusionsCount = resolvedExclusions.size();
|
||||||
if (oldTombstoneCount + newTombstoneCount > maxTombstoneCount) {
|
if (oldExclusionsCount + newExclusionsCount > maxExclusionsCount) {
|
||||||
throw new IllegalArgumentException("add voting tombstones request for " + Arrays.asList(nodeDescriptions)
|
throw new IllegalArgumentException("add voting config exclusions request for " + Arrays.asList(nodeDescriptions)
|
||||||
+ " would add [" + newTombstoneCount + "] voting tombstones to the existing [" + oldTombstoneCount
|
+ " would add [" + newExclusionsCount + "] exclusions to the existing [" + oldExclusionsCount
|
||||||
+ "] which would exceed the maximum of [" + maxTombstoneCount + "] set by ["
|
+ "] which would exceed the maximum of [" + maxExclusionsCount + "] set by ["
|
||||||
+ maximumSettingKey + "]");
|
+ maximumSettingKey + "]");
|
||||||
}
|
}
|
||||||
return resolvedNodes;
|
return resolvedExclusions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return descriptions of the nodes for whom to add tombstones.
|
* @return descriptions of the nodes for whom to add voting config exclusions.
|
||||||
*/
|
*/
|
||||||
public String[] getNodeDescriptions() {
|
public String[] getNodeDescriptions() {
|
||||||
return nodeDescriptions;
|
return nodeDescriptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return how long to wait after adding the tombstones for the nodes to be removed from the voting configuration.
|
* @return how long to wait after adding the exclusions for the nodes to be removed from the voting configuration.
|
||||||
*/
|
*/
|
||||||
public TimeValue getTimeout() {
|
public TimeValue getTimeout() {
|
||||||
return timeout;
|
return timeout;
|
||||||
|
@ -132,7 +132,7 @@ public class AddVotingTombstonesRequest extends MasterNodeRequest<AddVotingTombs
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "AddVotingTombstonesRequest{" +
|
return "AddVotingConfigExclusionsRequest{" +
|
||||||
"nodeDescriptions=" + Arrays.asList(nodeDescriptions) +
|
"nodeDescriptions=" + Arrays.asList(nodeDescriptions) +
|
||||||
", timeout=" + timeout +
|
", timeout=" + timeout +
|
||||||
'}';
|
'}';
|
|
@ -27,15 +27,15 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A response to {@link AddVotingTombstonesRequest} indicating that voting tombstones have been added for the requested nodes and these
|
* A response to {@link AddVotingConfigExclusionsRequest} indicating that voting config exclusions have been added for the requested nodes
|
||||||
* nodes have been removed from the voting configuration.
|
* and these nodes have been removed from the voting configuration.
|
||||||
*/
|
*/
|
||||||
public class AddVotingTombstonesResponse extends ActionResponse implements ToXContentObject {
|
public class AddVotingConfigExclusionsResponse extends ActionResponse implements ToXContentObject {
|
||||||
|
|
||||||
public AddVotingTombstonesResponse() {
|
public AddVotingConfigExclusionsResponse() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AddVotingTombstonesResponse(StreamInput in) throws IOException {
|
public AddVotingConfigExclusionsResponse(StreamInput in) throws IOException {
|
||||||
super(in);
|
super(in);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,21 +21,21 @@ package org.elasticsearch.action.admin.cluster.configuration;
|
||||||
import org.elasticsearch.action.Action;
|
import org.elasticsearch.action.Action;
|
||||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||||
|
|
||||||
public class ClearVotingTombstonesAction extends Action<ClearVotingTombstonesResponse> {
|
public class ClearVotingConfigExclusionsAction extends Action<ClearVotingConfigExclusionsResponse> {
|
||||||
public static final ClearVotingTombstonesAction INSTANCE = new ClearVotingTombstonesAction();
|
public static final ClearVotingConfigExclusionsAction INSTANCE = new ClearVotingConfigExclusionsAction();
|
||||||
public static final String NAME = "cluster:admin/voting/clear_tombstones";
|
public static final String NAME = "cluster:admin/voting_config/clear_exclusions";
|
||||||
|
|
||||||
private ClearVotingTombstonesAction() {
|
private ClearVotingConfigExclusionsAction() {
|
||||||
super(NAME);
|
super(NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClearVotingTombstonesResponse newResponse() {
|
public ClearVotingConfigExclusionsResponse newResponse() {
|
||||||
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
|
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Reader<ClearVotingTombstonesResponse> getResponseReader() {
|
public Reader<ClearVotingConfigExclusionsResponse> getResponseReader() {
|
||||||
return ClearVotingTombstonesResponse::new;
|
return ClearVotingConfigExclusionsResponse::new;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,41 +27,43 @@ import org.elasticsearch.common.unit.TimeValue;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A request to clear the voting tombstones from the cluster state, optionally waiting for these nodes to be removed from the cluster first.
|
* A request to clear the voting config exclusions from the cluster state, optionally waiting for these nodes to be removed from the
|
||||||
|
* cluster first.
|
||||||
*/
|
*/
|
||||||
public class ClearVotingTombstonesRequest extends MasterNodeRequest<ClearVotingTombstonesRequest> {
|
public class ClearVotingConfigExclusionsRequest extends MasterNodeRequest<ClearVotingConfigExclusionsRequest> {
|
||||||
private boolean waitForRemoval = true;
|
private boolean waitForRemoval = true;
|
||||||
private TimeValue timeout = TimeValue.timeValueSeconds(30);
|
private TimeValue timeout = TimeValue.timeValueSeconds(30);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a request to remove all the voting tombstones from the cluster state.
|
* Construct a request to remove all the voting config exclusions from the cluster state.
|
||||||
*/
|
*/
|
||||||
public ClearVotingTombstonesRequest() {
|
public ClearVotingConfigExclusionsRequest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClearVotingTombstonesRequest(StreamInput in) throws IOException {
|
public ClearVotingConfigExclusionsRequest(StreamInput in) throws IOException {
|
||||||
super(in);
|
super(in);
|
||||||
waitForRemoval = in.readBoolean();
|
waitForRemoval = in.readBoolean();
|
||||||
timeout = in.readTimeValue();
|
timeout = in.readTimeValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return whether to wait for the tombstoned nodes to be removed from the cluster before removing their tombstones. True by default.
|
* @return whether to wait for the currently excluded nodes to be removed from the cluster before removing their exclusions.
|
||||||
|
* True by default.
|
||||||
*/
|
*/
|
||||||
public boolean getWaitForRemoval() {
|
public boolean getWaitForRemoval() {
|
||||||
return waitForRemoval;
|
return waitForRemoval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param waitForRemoval whether to wait for the tombstoned nodes to be removed from the cluster before removing their tombstones. True
|
* @param waitForRemoval whether to wait for the currently excluded nodes to be removed from the cluster before removing their
|
||||||
* by default.
|
* exclusions. True by default.
|
||||||
*/
|
*/
|
||||||
public void setWaitForRemoval(boolean waitForRemoval) {
|
public void setWaitForRemoval(boolean waitForRemoval) {
|
||||||
this.waitForRemoval = waitForRemoval;
|
this.waitForRemoval = waitForRemoval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param timeout how long to wait for the tombstoned nodes to be removed if {@link ClearVotingTombstonesRequest#waitForRemoval} is
|
* @param timeout how long to wait for the excluded nodes to be removed if {@link ClearVotingConfigExclusionsRequest#waitForRemoval} is
|
||||||
* true. Defaults to 30 seconds.
|
* true. Defaults to 30 seconds.
|
||||||
*/
|
*/
|
||||||
public void setTimeout(TimeValue timeout) {
|
public void setTimeout(TimeValue timeout) {
|
||||||
|
@ -69,7 +71,7 @@ public class ClearVotingTombstonesRequest extends MasterNodeRequest<ClearVotingT
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return how long to wait for the tombstoned nodes to be removed if {@link ClearVotingTombstonesRequest#waitForRemoval} is
|
* @return how long to wait for the excluded nodes to be removed if {@link ClearVotingConfigExclusionsRequest#waitForRemoval} is
|
||||||
* true. Defaults to 30 seconds.
|
* true. Defaults to 30 seconds.
|
||||||
*/
|
*/
|
||||||
public TimeValue getTimeout() {
|
public TimeValue getTimeout() {
|
||||||
|
@ -95,7 +97,7 @@ public class ClearVotingTombstonesRequest extends MasterNodeRequest<ClearVotingT
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ClearVotingTombstonesRequest{" +
|
return "ClearVotingConfigExclusionsRequest{" +
|
||||||
", waitForRemoval=" + waitForRemoval +
|
", waitForRemoval=" + waitForRemoval +
|
||||||
", timeout=" + timeout +
|
", timeout=" + timeout +
|
||||||
'}';
|
'}';
|
|
@ -27,13 +27,14 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A response to {@link ClearVotingTombstonesRequest} indicating that voting tombstones have been cleared from the cluster state.
|
* A response to {@link ClearVotingConfigExclusionsRequest} indicating that voting config exclusions have been cleared from the
|
||||||
|
* cluster state.
|
||||||
*/
|
*/
|
||||||
public class ClearVotingTombstonesResponse extends ActionResponse implements ToXContentObject {
|
public class ClearVotingConfigExclusionsResponse extends ActionResponse implements ToXContentObject {
|
||||||
public ClearVotingTombstonesResponse() {
|
public ClearVotingConfigExclusionsResponse() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClearVotingTombstonesResponse(StreamInput in) throws IOException {
|
public ClearVotingConfigExclusionsResponse(StreamInput in) throws IOException {
|
||||||
super(in);
|
super(in);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
||||||
import org.elasticsearch.cluster.block.ClusterBlockException;
|
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||||
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
import org.elasticsearch.cluster.service.ClusterService;
|
import org.elasticsearch.cluster.service.ClusterService;
|
||||||
|
@ -49,16 +49,17 @@ import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class TransportAddVotingTombstonesAction extends TransportMasterNodeAction<AddVotingTombstonesRequest, AddVotingTombstonesResponse> {
|
public class TransportAddVotingConfigExclusionsAction extends TransportMasterNodeAction<AddVotingConfigExclusionsRequest,
|
||||||
|
AddVotingConfigExclusionsResponse> {
|
||||||
|
|
||||||
public static final Setting<Integer> MAXIMUM_VOTING_TOMBSTONES_SETTING
|
public static final Setting<Integer> MAXIMUM_VOTING_CONFIG_EXCLUSIONS_SETTING
|
||||||
= Setting.intSetting("cluster.max_voting_tombstones", 10, 1, Property.Dynamic, Property.NodeScope);
|
= Setting.intSetting("cluster.max_voting_config_exclusions", 10, 1, Property.Dynamic, Property.NodeScope);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public TransportAddVotingTombstonesAction(TransportService transportService, ClusterService clusterService, ThreadPool threadPool,
|
public TransportAddVotingConfigExclusionsAction(TransportService transportService, ClusterService clusterService, ThreadPool threadPool,
|
||||||
ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
|
ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||||
super(AddVotingTombstonesAction.NAME, transportService, clusterService, threadPool, actionFilters, AddVotingTombstonesRequest::new,
|
super(AddVotingConfigExclusionsAction.NAME, transportService, clusterService, threadPool, actionFilters,
|
||||||
indexNameExpressionResolver);
|
AddVotingConfigExclusionsRequest::new, indexNameExpressionResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -67,35 +68,36 @@ public class TransportAddVotingTombstonesAction extends TransportMasterNodeActio
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AddVotingTombstonesResponse newResponse() {
|
protected AddVotingConfigExclusionsResponse newResponse() {
|
||||||
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
|
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AddVotingTombstonesResponse read(StreamInput in) throws IOException {
|
protected AddVotingConfigExclusionsResponse read(StreamInput in) throws IOException {
|
||||||
return new AddVotingTombstonesResponse(in);
|
return new AddVotingConfigExclusionsResponse(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void masterOperation(AddVotingTombstonesRequest request, ClusterState state,
|
protected void masterOperation(AddVotingConfigExclusionsRequest request, ClusterState state,
|
||||||
ActionListener<AddVotingTombstonesResponse> listener) throws Exception {
|
ActionListener<AddVotingConfigExclusionsResponse> listener) throws Exception {
|
||||||
|
|
||||||
resolveVotingTombstonesAndCheckMaximum(request, state); // throws IllegalArgumentException if no nodes matched or maximum exceeded
|
resolveVotingConfigExclusionsAndCheckMaximum(request, state); // throws IAE if no nodes matched or maximum exceeded
|
||||||
|
|
||||||
clusterService.submitStateUpdateTask("add-voting-tombstones", new ClusterStateUpdateTask(Priority.URGENT) {
|
clusterService.submitStateUpdateTask("add-voting-config-exclusions", new ClusterStateUpdateTask(Priority.URGENT) {
|
||||||
|
|
||||||
private Set<VotingTombstone> resolvedNodes;
|
private Set<VotingConfigExclusion> resolvedExclusions;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClusterState execute(ClusterState currentState) {
|
public ClusterState execute(ClusterState currentState) {
|
||||||
assert resolvedNodes == null : resolvedNodes;
|
assert resolvedExclusions == null : resolvedExclusions;
|
||||||
resolvedNodes = resolveVotingTombstonesAndCheckMaximum(request, currentState);
|
resolvedExclusions = resolveVotingConfigExclusionsAndCheckMaximum(request, currentState);
|
||||||
|
|
||||||
final CoordinationMetaData.Builder builder = CoordinationMetaData.builder(currentState.coordinationMetaData());
|
final CoordinationMetaData.Builder builder = CoordinationMetaData.builder(currentState.coordinationMetaData());
|
||||||
resolvedNodes.forEach(builder::addVotingTombstone);
|
resolvedExclusions.forEach(builder::addVotingConfigExclusion);
|
||||||
final MetaData newMetaData = MetaData.builder(currentState.metaData()).coordinationMetaData(builder.build()).build();
|
final MetaData newMetaData = MetaData.builder(currentState.metaData()).coordinationMetaData(builder.build()).build();
|
||||||
final ClusterState newState = ClusterState.builder(currentState).metaData(newMetaData).build();
|
final ClusterState newState = ClusterState.builder(currentState).metaData(newMetaData).build();
|
||||||
assert newState.getVotingTombstones().size() <= MAXIMUM_VOTING_TOMBSTONES_SETTING.get(currentState.metaData().settings());
|
assert newState.getVotingConfigExclusions().size() <= MAXIMUM_VOTING_CONFIG_EXCLUSIONS_SETTING.get(
|
||||||
|
currentState.metaData().settings());
|
||||||
return newState;
|
return newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,29 +112,30 @@ public class TransportAddVotingTombstonesAction extends TransportMasterNodeActio
|
||||||
final ClusterStateObserver observer
|
final ClusterStateObserver observer
|
||||||
= new ClusterStateObserver(clusterService, request.getTimeout(), logger, threadPool.getThreadContext());
|
= new ClusterStateObserver(clusterService, request.getTimeout(), logger, threadPool.getThreadContext());
|
||||||
|
|
||||||
final Set<String> resolvedNodeIds = resolvedNodes.stream().map(VotingTombstone::getNodeId).collect(Collectors.toSet());
|
final Set<String> excludedNodeIds = resolvedExclusions.stream().map(VotingConfigExclusion::getNodeId)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
final Predicate<ClusterState> allNodesRemoved = clusterState -> {
|
final Predicate<ClusterState> allNodesRemoved = clusterState -> {
|
||||||
final Set<String> votingNodeIds = clusterState.getLastCommittedConfiguration().getNodeIds();
|
final Set<String> votingConfigNodeIds = clusterState.getLastCommittedConfiguration().getNodeIds();
|
||||||
return resolvedNodeIds.stream().noneMatch(votingNodeIds::contains);
|
return excludedNodeIds.stream().noneMatch(votingConfigNodeIds::contains);
|
||||||
};
|
};
|
||||||
|
|
||||||
final Listener clusterStateListener = new Listener() {
|
final Listener clusterStateListener = new Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void onNewClusterState(ClusterState state) {
|
public void onNewClusterState(ClusterState state) {
|
||||||
listener.onResponse(new AddVotingTombstonesResponse());
|
listener.onResponse(new AddVotingConfigExclusionsResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClusterServiceClose() {
|
public void onClusterServiceClose() {
|
||||||
listener.onFailure(new ElasticsearchException("cluster service closed while waiting for withdrawal of votes from "
|
listener.onFailure(new ElasticsearchException("cluster service closed while waiting for voting config exclusions " +
|
||||||
+ resolvedNodes));
|
resolvedExclusions + " to take effect"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimeout(TimeValue timeout) {
|
public void onTimeout(TimeValue timeout) {
|
||||||
listener.onFailure(new ElasticsearchTimeoutException("timed out waiting for withdrawal of votes from "
|
listener.onFailure(new ElasticsearchTimeoutException("timed out waiting for voting config exclusions "
|
||||||
+ resolvedNodes));
|
+ resolvedExclusions + " to take effect"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -145,13 +148,14 @@ public class TransportAddVotingTombstonesAction extends TransportMasterNodeActio
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Set<VotingTombstone> resolveVotingTombstonesAndCheckMaximum(AddVotingTombstonesRequest request, ClusterState state) {
|
private static Set<VotingConfigExclusion> resolveVotingConfigExclusionsAndCheckMaximum(AddVotingConfigExclusionsRequest request,
|
||||||
return request.resolveVotingTombstonesAndCheckMaximum(state,
|
ClusterState state) {
|
||||||
MAXIMUM_VOTING_TOMBSTONES_SETTING.get(state.metaData().settings()), MAXIMUM_VOTING_TOMBSTONES_SETTING.getKey());
|
return request.resolveVotingConfigExclusionsAndCheckMaximum(state,
|
||||||
|
MAXIMUM_VOTING_CONFIG_EXCLUSIONS_SETTING.get(state.metaData().settings()), MAXIMUM_VOTING_CONFIG_EXCLUSIONS_SETTING.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ClusterBlockException checkBlock(AddVotingTombstonesRequest request, ClusterState state) {
|
protected ClusterBlockException checkBlock(AddVotingConfigExclusionsRequest request, ClusterState state) {
|
||||||
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
|
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,7 +30,7 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
||||||
import org.elasticsearch.cluster.block.ClusterBlockException;
|
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||||
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
import org.elasticsearch.cluster.service.ClusterService;
|
import org.elasticsearch.cluster.service.ClusterService;
|
||||||
|
@ -45,14 +45,15 @@ import org.elasticsearch.transport.TransportService;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class TransportClearVotingTombstonesAction
|
public class TransportClearVotingConfigExclusionsAction
|
||||||
extends TransportMasterNodeAction<ClearVotingTombstonesRequest, ClearVotingTombstonesResponse> {
|
extends TransportMasterNodeAction<ClearVotingConfigExclusionsRequest, ClearVotingConfigExclusionsResponse> {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public TransportClearVotingTombstonesAction(TransportService transportService, ClusterService clusterService, ThreadPool threadPool,
|
public TransportClearVotingConfigExclusionsAction(TransportService transportService, ClusterService clusterService,
|
||||||
ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
|
ThreadPool threadPool, ActionFilters actionFilters,
|
||||||
super(ClearVotingTombstonesAction.NAME, transportService, clusterService, threadPool, actionFilters,
|
IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||||
ClearVotingTombstonesRequest::new, indexNameExpressionResolver);
|
super(ClearVotingConfigExclusionsAction.NAME, transportService, clusterService, threadPool, actionFilters,
|
||||||
|
ClearVotingConfigExclusionsRequest::new, indexNameExpressionResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,23 +62,23 @@ public class TransportClearVotingTombstonesAction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ClearVotingTombstonesResponse newResponse() {
|
protected ClearVotingConfigExclusionsResponse newResponse() {
|
||||||
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
|
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ClearVotingTombstonesResponse read(StreamInput in) throws IOException {
|
protected ClearVotingConfigExclusionsResponse read(StreamInput in) throws IOException {
|
||||||
return new ClearVotingTombstonesResponse(in);
|
return new ClearVotingConfigExclusionsResponse(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void masterOperation(ClearVotingTombstonesRequest request, ClusterState initialState,
|
protected void masterOperation(ClearVotingConfigExclusionsRequest request, ClusterState initialState,
|
||||||
ActionListener<ClearVotingTombstonesResponse> listener) throws Exception {
|
ActionListener<ClearVotingConfigExclusionsResponse> listener) throws Exception {
|
||||||
|
|
||||||
final long startTimeMillis = threadPool.relativeTimeInMillis();
|
final long startTimeMillis = threadPool.relativeTimeInMillis();
|
||||||
|
|
||||||
final Predicate<ClusterState> allTombstonedNodesRemoved = newState -> {
|
final Predicate<ClusterState> allExclusionsRemoved = newState -> {
|
||||||
for (VotingTombstone tombstone : initialState.getVotingTombstones()) {
|
for (VotingConfigExclusion tombstone : initialState.getVotingConfigExclusions()) {
|
||||||
// NB checking for the existence of any node with this persistent ID, because persistent IDs are how votes are counted.
|
// NB checking for the existence of any node with this persistent ID, because persistent IDs are how votes are counted.
|
||||||
if (newState.nodes().nodeExists(tombstone.getNodeId())) {
|
if (newState.nodes().nodeExists(tombstone.getNodeId())) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -86,41 +87,41 @@ public class TransportClearVotingTombstonesAction
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (request.getWaitForRemoval() && allTombstonedNodesRemoved.test(initialState) == false) {
|
if (request.getWaitForRemoval() && allExclusionsRemoved.test(initialState) == false) {
|
||||||
final ClusterStateObserver clusterStateObserver = new ClusterStateObserver(initialState, clusterService, request.getTimeout(),
|
final ClusterStateObserver clusterStateObserver = new ClusterStateObserver(initialState, clusterService, request.getTimeout(),
|
||||||
logger, threadPool.getThreadContext());
|
logger, threadPool.getThreadContext());
|
||||||
|
|
||||||
clusterStateObserver.waitForNextChange(new Listener() {
|
clusterStateObserver.waitForNextChange(new Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void onNewClusterState(ClusterState state) {
|
public void onNewClusterState(ClusterState state) {
|
||||||
submitClearTombstonesTask(request, startTimeMillis, listener);
|
submitClearVotingConfigExclusionsTask(request, startTimeMillis, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClusterServiceClose() {
|
public void onClusterServiceClose() {
|
||||||
listener.onFailure(new ElasticsearchException("cluster service closed while waiting for removal of nodes "
|
listener.onFailure(new ElasticsearchException("cluster service closed while waiting for removal of nodes "
|
||||||
+ initialState.getVotingTombstones()));
|
+ initialState.getVotingConfigExclusions()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimeout(TimeValue timeout) {
|
public void onTimeout(TimeValue timeout) {
|
||||||
listener.onFailure(new ElasticsearchTimeoutException(
|
listener.onFailure(new ElasticsearchTimeoutException(
|
||||||
"timed out waiting for removal of nodes; if nodes should not be removed, set waitForRemoval to false. "
|
"timed out waiting for removal of nodes; if nodes should not be removed, set waitForRemoval to false. "
|
||||||
+ initialState.getVotingTombstones()));
|
+ initialState.getVotingConfigExclusions()));
|
||||||
}
|
}
|
||||||
}, allTombstonedNodesRemoved);
|
}, allExclusionsRemoved);
|
||||||
} else {
|
} else {
|
||||||
submitClearTombstonesTask(request, startTimeMillis, listener);
|
submitClearVotingConfigExclusionsTask(request, startTimeMillis, listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void submitClearTombstonesTask(ClearVotingTombstonesRequest request, long startTimeMillis,
|
private void submitClearVotingConfigExclusionsTask(ClearVotingConfigExclusionsRequest request, long startTimeMillis,
|
||||||
ActionListener<ClearVotingTombstonesResponse> listener) {
|
ActionListener<ClearVotingConfigExclusionsResponse> listener) {
|
||||||
clusterService.submitStateUpdateTask("clear-voting-tombstones", new ClusterStateUpdateTask(Priority.URGENT) {
|
clusterService.submitStateUpdateTask("clear-voting-config-exclusions", new ClusterStateUpdateTask(Priority.URGENT) {
|
||||||
@Override
|
@Override
|
||||||
public ClusterState execute(ClusterState currentState) {
|
public ClusterState execute(ClusterState currentState) {
|
||||||
final CoordinationMetaData newCoordinationMetaData =
|
final CoordinationMetaData newCoordinationMetaData =
|
||||||
CoordinationMetaData.builder(currentState.coordinationMetaData()).clearVotingTombstones().build();
|
CoordinationMetaData.builder(currentState.coordinationMetaData()).clearVotingConfigExclusions().build();
|
||||||
final MetaData newMetaData = MetaData.builder(currentState.metaData()).
|
final MetaData newMetaData = MetaData.builder(currentState.metaData()).
|
||||||
coordinationMetaData(newCoordinationMetaData).build();
|
coordinationMetaData(newCoordinationMetaData).build();
|
||||||
return ClusterState.builder(currentState).metaData(newMetaData).build();
|
return ClusterState.builder(currentState).metaData(newMetaData).build();
|
||||||
|
@ -138,13 +139,13 @@ public class TransportClearVotingTombstonesAction
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
|
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
|
||||||
listener.onResponse(new ClearVotingTombstonesResponse());
|
listener.onResponse(new ClearVotingConfigExclusionsResponse());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ClusterBlockException checkBlock(ClearVotingTombstonesRequest request, ClusterState state) {
|
protected ClusterBlockException checkBlock(ClearVotingConfigExclusionsRequest request, ClusterState state) {
|
||||||
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
|
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -28,7 +28,7 @@ import org.elasticsearch.cluster.block.ClusterBlock;
|
||||||
import org.elasticsearch.cluster.block.ClusterBlocks;
|
import org.elasticsearch.cluster.block.ClusterBlocks;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||||
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
|
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
|
||||||
import org.elasticsearch.cluster.metadata.MappingMetaData;
|
import org.elasticsearch.cluster.metadata.MappingMetaData;
|
||||||
|
@ -278,8 +278,8 @@ public class ClusterState implements ToXContentFragment, Diffable<ClusterState>
|
||||||
return coordinationMetaData().getLastCommittedConfiguration();
|
return coordinationMetaData().getLastCommittedConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<VotingTombstone> getVotingTombstones() {
|
public Set<VotingConfigExclusion> getVotingConfigExclusions() {
|
||||||
return coordinationMetaData().getVotingTombstones();
|
return coordinationMetaData().getVotingConfigExclusions();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for testing and logging to determine how this cluster state was send over the wire
|
// Used for testing and logging to determine how this cluster state was send over the wire
|
||||||
|
@ -314,7 +314,7 @@ public class ClusterState implements ToXContentFragment, Diffable<ClusterState>
|
||||||
sb.append(TAB).append(TAB)
|
sb.append(TAB).append(TAB)
|
||||||
.append("last_accepted_config: ").append(coordinationMetaData().getLastAcceptedConfiguration()).append("\n");
|
.append("last_accepted_config: ").append(coordinationMetaData().getLastAcceptedConfiguration()).append("\n");
|
||||||
sb.append(TAB).append(TAB)
|
sb.append(TAB).append(TAB)
|
||||||
.append("voting tombstones: ").append(coordinationMetaData().getVotingTombstones()).append("\n");
|
.append("voting tombstones: ").append(coordinationMetaData().getVotingConfigExclusions()).append("\n");
|
||||||
for (IndexMetaData indexMetaData : metaData) {
|
for (IndexMetaData indexMetaData : metaData) {
|
||||||
sb.append(TAB).append(indexMetaData.getIndex());
|
sb.append(TAB).append(indexMetaData.getIndex());
|
||||||
sb.append(": v[").append(indexMetaData.getVersion())
|
sb.append(": v[").append(indexMetaData.getVersion())
|
||||||
|
|
|
@ -49,12 +49,12 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
|
|
||||||
private final VotingConfiguration lastAcceptedConfiguration;
|
private final VotingConfiguration lastAcceptedConfiguration;
|
||||||
|
|
||||||
private final Set<VotingTombstone> votingTombstones;
|
private final Set<VotingConfigExclusion> votingConfigExclusions;
|
||||||
|
|
||||||
private static final ParseField TERM_PARSE_FIELD = new ParseField("term");
|
private static final ParseField TERM_PARSE_FIELD = new ParseField("term");
|
||||||
private static final ParseField LAST_COMMITTED_CONFIGURATION_FIELD = new ParseField("last_committed_config");
|
private static final ParseField LAST_COMMITTED_CONFIGURATION_FIELD = new ParseField("last_committed_config");
|
||||||
private static final ParseField LAST_ACCEPTED_CONFIGURATION_FIELD = new ParseField("last_accepted_config");
|
private static final ParseField LAST_ACCEPTED_CONFIGURATION_FIELD = new ParseField("last_accepted_config");
|
||||||
private static final ParseField VOTING_TOMBSTONES_FIELD = new ParseField("voting_tombstones");
|
private static final ParseField VOTING_CONFIG_EXCLUSIONS_FIELD = new ParseField("voting_config_exclusions");
|
||||||
|
|
||||||
private static long term(Object[] termAndConfigs) {
|
private static long term(Object[] termAndConfigs) {
|
||||||
return (long)termAndConfigs[0];
|
return (long)termAndConfigs[0];
|
||||||
|
@ -73,35 +73,35 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static Set<VotingTombstone> votingTombstones(Object[] fields) {
|
private static Set<VotingConfigExclusion> votingConfigExclusions(Object[] fields) {
|
||||||
Set<VotingTombstone> votingTombstones = new HashSet<>((List<VotingTombstone>) fields[3]);
|
Set<VotingConfigExclusion> votingTombstones = new HashSet<>((List<VotingConfigExclusion>) fields[3]);
|
||||||
return votingTombstones;
|
return votingTombstones;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final ConstructingObjectParser<CoordinationMetaData, Void> PARSER = new ConstructingObjectParser<>(
|
private static final ConstructingObjectParser<CoordinationMetaData, Void> PARSER = new ConstructingObjectParser<>(
|
||||||
"coordination_metadata",
|
"coordination_metadata",
|
||||||
fields -> new CoordinationMetaData(term(fields), lastCommittedConfig(fields),
|
fields -> new CoordinationMetaData(term(fields), lastCommittedConfig(fields),
|
||||||
lastAcceptedConfig(fields), votingTombstones(fields)));
|
lastAcceptedConfig(fields), votingConfigExclusions(fields)));
|
||||||
static {
|
static {
|
||||||
PARSER.declareLong(ConstructingObjectParser.constructorArg(), TERM_PARSE_FIELD);
|
PARSER.declareLong(ConstructingObjectParser.constructorArg(), TERM_PARSE_FIELD);
|
||||||
PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), LAST_COMMITTED_CONFIGURATION_FIELD);
|
PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), LAST_COMMITTED_CONFIGURATION_FIELD);
|
||||||
PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), LAST_ACCEPTED_CONFIGURATION_FIELD);
|
PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), LAST_ACCEPTED_CONFIGURATION_FIELD);
|
||||||
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), VotingTombstone.PARSER, VOTING_TOMBSTONES_FIELD);
|
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), VotingConfigExclusion.PARSER, VOTING_CONFIG_EXCLUSIONS_FIELD);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CoordinationMetaData(long term, VotingConfiguration lastCommittedConfiguration, VotingConfiguration lastAcceptedConfiguration,
|
public CoordinationMetaData(long term, VotingConfiguration lastCommittedConfiguration, VotingConfiguration lastAcceptedConfiguration,
|
||||||
Set<VotingTombstone> votingTombstones) {
|
Set<VotingConfigExclusion> votingConfigExclusions) {
|
||||||
this.term = term;
|
this.term = term;
|
||||||
this.lastCommittedConfiguration = lastCommittedConfiguration;
|
this.lastCommittedConfiguration = lastCommittedConfiguration;
|
||||||
this.lastAcceptedConfiguration = lastAcceptedConfiguration;
|
this.lastAcceptedConfiguration = lastAcceptedConfiguration;
|
||||||
this.votingTombstones = Collections.unmodifiableSet(new HashSet<>(votingTombstones));
|
this.votingConfigExclusions = Collections.unmodifiableSet(new HashSet<>(votingConfigExclusions));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CoordinationMetaData(StreamInput in) throws IOException {
|
public CoordinationMetaData(StreamInput in) throws IOException {
|
||||||
term = in.readLong();
|
term = in.readLong();
|
||||||
lastCommittedConfiguration = new VotingConfiguration(in);
|
lastCommittedConfiguration = new VotingConfiguration(in);
|
||||||
lastAcceptedConfiguration = new VotingConfiguration(in);
|
lastAcceptedConfiguration = new VotingConfiguration(in);
|
||||||
votingTombstones = Collections.unmodifiableSet(in.readSet(VotingTombstone::new));
|
votingConfigExclusions = Collections.unmodifiableSet(in.readSet(VotingConfigExclusion::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
|
@ -117,7 +117,7 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
out.writeLong(term);
|
out.writeLong(term);
|
||||||
lastCommittedConfiguration.writeTo(out);
|
lastCommittedConfiguration.writeTo(out);
|
||||||
lastAcceptedConfiguration.writeTo(out);
|
lastAcceptedConfiguration.writeTo(out);
|
||||||
out.writeCollection(votingTombstones, (o, v) -> v.writeTo(o));
|
out.writeCollection(votingConfigExclusions, (o, v) -> v.writeTo(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -126,7 +126,7 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
.field(TERM_PARSE_FIELD.getPreferredName(), term)
|
.field(TERM_PARSE_FIELD.getPreferredName(), term)
|
||||||
.field(LAST_COMMITTED_CONFIGURATION_FIELD.getPreferredName(), lastCommittedConfiguration)
|
.field(LAST_COMMITTED_CONFIGURATION_FIELD.getPreferredName(), lastCommittedConfiguration)
|
||||||
.field(LAST_ACCEPTED_CONFIGURATION_FIELD.getPreferredName(), lastAcceptedConfiguration)
|
.field(LAST_ACCEPTED_CONFIGURATION_FIELD.getPreferredName(), lastAcceptedConfiguration)
|
||||||
.field(VOTING_TOMBSTONES_FIELD.getPreferredName(), votingTombstones);
|
.field(VOTING_CONFIG_EXCLUSIONS_FIELD.getPreferredName(), votingConfigExclusions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CoordinationMetaData fromXContent(XContentParser parser) throws IOException {
|
public static CoordinationMetaData fromXContent(XContentParser parser) throws IOException {
|
||||||
|
@ -145,8 +145,8 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
return lastCommittedConfiguration;
|
return lastCommittedConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<VotingTombstone> getVotingTombstones() {
|
public Set<VotingConfigExclusion> getVotingConfigExclusions() {
|
||||||
return votingTombstones;
|
return votingConfigExclusions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -159,7 +159,7 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
if (term != that.term) return false;
|
if (term != that.term) return false;
|
||||||
if (!lastCommittedConfiguration.equals(that.lastCommittedConfiguration)) return false;
|
if (!lastCommittedConfiguration.equals(that.lastCommittedConfiguration)) return false;
|
||||||
if (!lastAcceptedConfiguration.equals(that.lastAcceptedConfiguration)) return false;
|
if (!lastAcceptedConfiguration.equals(that.lastAcceptedConfiguration)) return false;
|
||||||
return votingTombstones.equals(that.votingTombstones);
|
return votingConfigExclusions.equals(that.votingConfigExclusions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -167,7 +167,7 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
int result = (int) (term ^ (term >>> 32));
|
int result = (int) (term ^ (term >>> 32));
|
||||||
result = 31 * result + lastCommittedConfiguration.hashCode();
|
result = 31 * result + lastCommittedConfiguration.hashCode();
|
||||||
result = 31 * result + lastAcceptedConfiguration.hashCode();
|
result = 31 * result + lastAcceptedConfiguration.hashCode();
|
||||||
result = 31 * result + votingTombstones.hashCode();
|
result = 31 * result + votingConfigExclusions.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
"term=" + term +
|
"term=" + term +
|
||||||
", lastCommittedConfiguration=" + lastCommittedConfiguration +
|
", lastCommittedConfiguration=" + lastCommittedConfiguration +
|
||||||
", lastAcceptedConfiguration=" + lastAcceptedConfiguration +
|
", lastAcceptedConfiguration=" + lastAcceptedConfiguration +
|
||||||
", votingTombstones=" + votingTombstones +
|
", votingConfigExclusions=" + votingConfigExclusions +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
private long term = 0;
|
private long term = 0;
|
||||||
private VotingConfiguration lastCommittedConfiguration = VotingConfiguration.EMPTY_CONFIG;
|
private VotingConfiguration lastCommittedConfiguration = VotingConfiguration.EMPTY_CONFIG;
|
||||||
private VotingConfiguration lastAcceptedConfiguration = VotingConfiguration.EMPTY_CONFIG;
|
private VotingConfiguration lastAcceptedConfiguration = VotingConfiguration.EMPTY_CONFIG;
|
||||||
private final Set<VotingTombstone> votingTombstones = new HashSet<>();
|
private final Set<VotingConfigExclusion> votingConfigExclusions = new HashSet<>();
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
this.term = state.term;
|
this.term = state.term;
|
||||||
this.lastCommittedConfiguration = state.lastCommittedConfiguration;
|
this.lastCommittedConfiguration = state.lastCommittedConfiguration;
|
||||||
this.lastAcceptedConfiguration = state.lastAcceptedConfiguration;
|
this.lastAcceptedConfiguration = state.lastAcceptedConfiguration;
|
||||||
this.votingTombstones.addAll(state.votingTombstones);
|
this.votingConfigExclusions.addAll(state.votingConfigExclusions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder term(long term) {
|
public Builder term(long term) {
|
||||||
|
@ -213,35 +213,35 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder addVotingTombstone(VotingTombstone tombstone) {
|
public Builder addVotingConfigExclusion(VotingConfigExclusion exclusion) {
|
||||||
votingTombstones.add(tombstone);
|
votingConfigExclusions.add(exclusion);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder clearVotingTombstones() {
|
public Builder clearVotingConfigExclusions() {
|
||||||
votingTombstones.clear();
|
votingConfigExclusions.clear();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CoordinationMetaData build() {
|
public CoordinationMetaData build() {
|
||||||
return new CoordinationMetaData(term, lastCommittedConfiguration, lastAcceptedConfiguration, votingTombstones);
|
return new CoordinationMetaData(term, lastCommittedConfiguration, lastAcceptedConfiguration, votingConfigExclusions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class VotingTombstone implements Writeable, ToXContentFragment {
|
public static class VotingConfigExclusion implements Writeable, ToXContentFragment {
|
||||||
private final String nodeId;
|
private final String nodeId;
|
||||||
private final String nodeName;
|
private final String nodeName;
|
||||||
|
|
||||||
public VotingTombstone(DiscoveryNode node) {
|
public VotingConfigExclusion(DiscoveryNode node) {
|
||||||
this(node.getId(), node.getName());
|
this(node.getId(), node.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public VotingTombstone(StreamInput in) throws IOException {
|
public VotingConfigExclusion(StreamInput in) throws IOException {
|
||||||
this.nodeId = in.readString();
|
this.nodeId = in.readString();
|
||||||
this.nodeName = in.readString();
|
this.nodeName = in.readString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public VotingTombstone(String nodeId, String nodeName) {
|
public VotingConfigExclusion(String nodeId, String nodeName) {
|
||||||
this.nodeId = nodeId;
|
this.nodeId = nodeId;
|
||||||
this.nodeName = nodeName;
|
this.nodeName = nodeName;
|
||||||
}
|
}
|
||||||
|
@ -271,9 +271,9 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
return (String) nodeIdAndName[1];
|
return (String) nodeIdAndName[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final ConstructingObjectParser<VotingTombstone, Void> PARSER = new ConstructingObjectParser<>(
|
private static final ConstructingObjectParser<VotingConfigExclusion, Void> PARSER = new ConstructingObjectParser<>(
|
||||||
"voting_tombstone",
|
"voting_config_exclusion",
|
||||||
nodeIdAndName -> new VotingTombstone(nodeId(nodeIdAndName), nodeName(nodeIdAndName))
|
nodeIdAndName -> new VotingConfigExclusion(nodeId(nodeIdAndName), nodeName(nodeIdAndName))
|
||||||
);
|
);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -281,7 +281,7 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), NODE_NAME_PARSE_FIELD);
|
PARSER.declareString(ConstructingObjectParser.constructorArg(), NODE_NAME_PARSE_FIELD);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VotingTombstone fromXContent(XContentParser parser) throws IOException {
|
public static VotingConfigExclusion fromXContent(XContentParser parser) throws IOException {
|
||||||
return PARSER.parse(parser, null);
|
return PARSER.parse(parser, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ public class CoordinationMetaData implements Writeable, ToXContentFragment {
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
VotingTombstone that = (VotingTombstone) o;
|
VotingConfigExclusion that = (VotingConfigExclusion) o;
|
||||||
return Objects.equals(nodeId, that.nodeId) &&
|
return Objects.equals(nodeId, that.nodeId) &&
|
||||||
Objects.equals(nodeName, that.nodeName);
|
Objects.equals(nodeName, that.nodeName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.elasticsearch.cluster.ClusterStateTaskConfig;
|
||||||
import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
||||||
import org.elasticsearch.cluster.block.ClusterBlocks;
|
import org.elasticsearch.cluster.block.ClusterBlocks;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.cluster.coordination.FollowersChecker.FollowerCheckRequest;
|
import org.elasticsearch.cluster.coordination.FollowersChecker.FollowerCheckRequest;
|
||||||
import org.elasticsearch.cluster.coordination.JoinHelper.InitialJoinAccumulator;
|
import org.elasticsearch.cluster.coordination.JoinHelper.InitialJoinAccumulator;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
|
@ -671,7 +671,7 @@ public class Coordinator extends AbstractLifecycleComponent implements Discovery
|
||||||
final Set<DiscoveryNode> liveNodes = StreamSupport.stream(clusterState.nodes().spliterator(), false)
|
final Set<DiscoveryNode> liveNodes = StreamSupport.stream(clusterState.nodes().spliterator(), false)
|
||||||
.filter(this::hasJoinVoteFrom).collect(Collectors.toSet());
|
.filter(this::hasJoinVoteFrom).collect(Collectors.toSet());
|
||||||
final VotingConfiguration newConfig = reconfigurator.reconfigure(liveNodes,
|
final VotingConfiguration newConfig = reconfigurator.reconfigure(liveNodes,
|
||||||
clusterState.getVotingTombstones().stream().map(VotingTombstone::getNodeId).collect(Collectors.toSet()),
|
clusterState.getVotingConfigExclusions().stream().map(VotingConfigExclusion::getNodeId).collect(Collectors.toSet()),
|
||||||
clusterState.getLastAcceptedConfiguration());
|
clusterState.getLastAcceptedConfiguration());
|
||||||
if (newConfig.equals(clusterState.getLastAcceptedConfiguration()) == false) {
|
if (newConfig.equals(clusterState.getLastAcceptedConfiguration()) == false) {
|
||||||
assert coordinationState.get().joinVotesHaveQuorumFor(newConfig);
|
assert coordinationState.get().joinVotesHaveQuorumFor(newConfig);
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
package org.elasticsearch.common.settings;
|
package org.elasticsearch.common.settings;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.TransportAddVotingTombstonesAction;
|
import org.elasticsearch.action.admin.cluster.configuration.TransportAddVotingConfigExclusionsAction;
|
||||||
import org.elasticsearch.action.admin.indices.close.TransportCloseIndexAction;
|
import org.elasticsearch.action.admin.indices.close.TransportCloseIndexAction;
|
||||||
import org.elasticsearch.action.search.TransportSearchAction;
|
import org.elasticsearch.action.search.TransportSearchAction;
|
||||||
import org.elasticsearch.action.support.AutoCreateIndex;
|
import org.elasticsearch.action.support.AutoCreateIndex;
|
||||||
|
@ -470,7 +470,7 @@ public final class ClusterSettings extends AbstractScopedSettings {
|
||||||
LeaderChecker.LEADER_CHECK_INTERVAL_SETTING,
|
LeaderChecker.LEADER_CHECK_INTERVAL_SETTING,
|
||||||
LeaderChecker.LEADER_CHECK_RETRY_COUNT_SETTING,
|
LeaderChecker.LEADER_CHECK_RETRY_COUNT_SETTING,
|
||||||
Reconfigurator.CLUSTER_AUTO_SHRINK_VOTING_CONFIGURATION,
|
Reconfigurator.CLUSTER_AUTO_SHRINK_VOTING_CONFIGURATION,
|
||||||
TransportAddVotingTombstonesAction.MAXIMUM_VOTING_TOMBSTONES_SETTING,
|
TransportAddVotingConfigExclusionsAction.MAXIMUM_VOTING_CONFIG_EXCLUSIONS_SETTING,
|
||||||
ClusterBootstrapService.INITIAL_MASTER_NODES_SETTING,
|
ClusterBootstrapService.INITIAL_MASTER_NODES_SETTING,
|
||||||
ClusterBootstrapService.INITIAL_MASTER_NODE_COUNT_SETTING,
|
ClusterBootstrapService.INITIAL_MASTER_NODE_COUNT_SETTING,
|
||||||
LagDetector.CLUSTER_FOLLOWER_LAG_TIMEOUT_SETTING
|
LagDetector.CLUSTER_FOLLOWER_LAG_TIMEOUT_SETTING
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
package org.elasticsearch.rest.action.admin.cluster;
|
package org.elasticsearch.rest.action.admin.cluster;
|
||||||
|
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.AddVotingTombstonesAction;
|
import org.elasticsearch.action.admin.cluster.configuration.AddVotingConfigExclusionsRequest;
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.AddVotingTombstonesRequest;
|
import org.elasticsearch.action.admin.cluster.configuration.AddVotingConfigExclusionsAction;
|
||||||
import org.elasticsearch.client.node.NodeClient;
|
import org.elasticsearch.client.node.NodeClient;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
@ -31,30 +31,30 @@ import org.elasticsearch.rest.action.RestToXContentListener;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class RestAddVotingTombstonesAction extends BaseRestHandler {
|
public class RestAddVotingConfigExclusionAction extends BaseRestHandler {
|
||||||
|
|
||||||
private static final TimeValue DEFAULT_TIMEOUT = TimeValue.timeValueSeconds(30L);
|
private static final TimeValue DEFAULT_TIMEOUT = TimeValue.timeValueSeconds(30L);
|
||||||
|
|
||||||
public RestAddVotingTombstonesAction(Settings settings, RestController controller) {
|
public RestAddVotingConfigExclusionAction(Settings settings, RestController controller) {
|
||||||
super(settings);
|
super(settings);
|
||||||
controller.registerHandler(RestRequest.Method.POST, "/_cluster/withdrawn_votes/{node_name}", this);
|
controller.registerHandler(RestRequest.Method.POST, "/_cluster/voting_config_exclusions/{node_name}", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "add_voting_tombstones_action";
|
return "add_voting_config_exclusions_action";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
protected RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
||||||
String nodeName = request.param("node_name");
|
String nodeName = request.param("node_name");
|
||||||
AddVotingTombstonesRequest addVotingTombstonesRequest = new AddVotingTombstonesRequest(
|
AddVotingConfigExclusionsRequest votingConfigExclusionsRequest = new AddVotingConfigExclusionsRequest(
|
||||||
new String[]{nodeName},
|
new String[]{nodeName},
|
||||||
TimeValue.parseTimeValue(request.param("timeout"), DEFAULT_TIMEOUT, getClass().getSimpleName() + ".timeout")
|
TimeValue.parseTimeValue(request.param("timeout"), DEFAULT_TIMEOUT, getClass().getSimpleName() + ".timeout")
|
||||||
);
|
);
|
||||||
return channel -> client.execute(
|
return channel -> client.execute(
|
||||||
AddVotingTombstonesAction.INSTANCE,
|
AddVotingConfigExclusionsAction.INSTANCE,
|
||||||
addVotingTombstonesRequest,
|
votingConfigExclusionsRequest,
|
||||||
new RestToXContentListener<>(channel)
|
new RestToXContentListener<>(channel)
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
package org.elasticsearch.rest.action.admin.cluster;
|
package org.elasticsearch.rest.action.admin.cluster;
|
||||||
|
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingTombstonesAction;
|
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingConfigExclusionsRequest;
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingTombstonesRequest;
|
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingConfigExclusionsAction;
|
||||||
import org.elasticsearch.client.node.NodeClient;
|
import org.elasticsearch.client.node.NodeClient;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.rest.BaseRestHandler;
|
import org.elasticsearch.rest.BaseRestHandler;
|
||||||
|
@ -30,24 +30,24 @@ import org.elasticsearch.rest.action.RestToXContentListener;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class RestClearVotingTombstonesAction extends BaseRestHandler {
|
public class RestClearVotingConfigExclusionsAction extends BaseRestHandler {
|
||||||
|
|
||||||
public RestClearVotingTombstonesAction(Settings settings, RestController controller) {
|
public RestClearVotingConfigExclusionsAction(Settings settings, RestController controller) {
|
||||||
super(settings);
|
super(settings);
|
||||||
controller.registerHandler(RestRequest.Method.DELETE, "/_cluster/withdrawn_votes", this);
|
controller.registerHandler(RestRequest.Method.DELETE, "/_cluster/voting_config_exclusions", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "clear_voting_tombstones_action";
|
return "clear_voting_config_exclusions_action";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
protected RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
||||||
ClearVotingTombstonesRequest req = new ClearVotingTombstonesRequest();
|
ClearVotingConfigExclusionsRequest req = new ClearVotingConfigExclusionsRequest();
|
||||||
if (request.hasParam("wait_for_removal")) {
|
if (request.hasParam("wait_for_removal")) {
|
||||||
req.setWaitForRemoval(request.paramAsBoolean("wait_for_removal", true));
|
req.setWaitForRemoval(request.paramAsBoolean("wait_for_removal", true));
|
||||||
}
|
}
|
||||||
return channel -> client.execute(ClearVotingTombstonesAction.INSTANCE, req, new RestToXContentListener<>(channel));
|
return channel -> client.execute(ClearVotingConfigExclusionsAction.INSTANCE, req, new RestToXContentListener<>(channel));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.cluster.ClusterName;
|
import org.elasticsearch.cluster.ClusterName;
|
||||||
import org.elasticsearch.cluster.ClusterState;
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNode.Role;
|
import org.elasticsearch.cluster.node.DiscoveryNode.Role;
|
||||||
|
@ -39,7 +39,7 @@ import static org.hamcrest.Matchers.contains;
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
public class AddVotingTombstonesRequestTests extends ESTestCase {
|
public class AddVotingConfigExclusionsRequestTests extends ESTestCase {
|
||||||
public void testSerialization() throws IOException {
|
public void testSerialization() throws IOException {
|
||||||
int descriptionCount = between(0, 5);
|
int descriptionCount = between(0, 5);
|
||||||
String[] descriptions = new String[descriptionCount];
|
String[] descriptions = new String[descriptionCount];
|
||||||
|
@ -47,8 +47,9 @@ public class AddVotingTombstonesRequestTests extends ESTestCase {
|
||||||
descriptions[i] = randomAlphaOfLength(10);
|
descriptions[i] = randomAlphaOfLength(10);
|
||||||
}
|
}
|
||||||
TimeValue timeout = TimeValue.timeValueMillis(between(0, 30000));
|
TimeValue timeout = TimeValue.timeValueMillis(between(0, 30000));
|
||||||
final AddVotingTombstonesRequest originalRequest = new AddVotingTombstonesRequest(descriptions, timeout);
|
final AddVotingConfigExclusionsRequest originalRequest = new AddVotingConfigExclusionsRequest(descriptions, timeout);
|
||||||
final AddVotingTombstonesRequest deserialized = copyWriteable(originalRequest, writableRegistry(), AddVotingTombstonesRequest::new);
|
final AddVotingConfigExclusionsRequest deserialized = copyWriteable(originalRequest, writableRegistry(),
|
||||||
|
AddVotingConfigExclusionsRequest::new);
|
||||||
assertThat(deserialized.getNodeDescriptions(), equalTo(originalRequest.getNodeDescriptions()));
|
assertThat(deserialized.getNodeDescriptions(), equalTo(originalRequest.getNodeDescriptions()));
|
||||||
assertThat(deserialized.getTimeout(), equalTo(originalRequest.getTimeout()));
|
assertThat(deserialized.getTimeout(), equalTo(originalRequest.getTimeout()));
|
||||||
}
|
}
|
||||||
|
@ -56,66 +57,66 @@ public class AddVotingTombstonesRequestTests extends ESTestCase {
|
||||||
public void testResolve() {
|
public void testResolve() {
|
||||||
final DiscoveryNode localNode
|
final DiscoveryNode localNode
|
||||||
= new DiscoveryNode("local", "local", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
= new DiscoveryNode("local", "local", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
||||||
final VotingTombstone localNodeTombstone = new VotingTombstone(localNode);
|
final VotingConfigExclusion localNodeExclusion = new VotingConfigExclusion(localNode);
|
||||||
final DiscoveryNode otherNode1
|
final DiscoveryNode otherNode1
|
||||||
= new DiscoveryNode("other1", "other1", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
= new DiscoveryNode("other1", "other1", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
||||||
final VotingTombstone otherNode1Tombstone = new VotingTombstone(otherNode1);
|
final VotingConfigExclusion otherNode1Exclusion = new VotingConfigExclusion(otherNode1);
|
||||||
final DiscoveryNode otherNode2
|
final DiscoveryNode otherNode2
|
||||||
= new DiscoveryNode("other2", "other2", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
= new DiscoveryNode("other2", "other2", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
||||||
final VotingTombstone otherNode2Tombstone = new VotingTombstone(otherNode2);
|
final VotingConfigExclusion otherNode2Exclusion = new VotingConfigExclusion(otherNode2);
|
||||||
final DiscoveryNode otherDataNode
|
final DiscoveryNode otherDataNode
|
||||||
= new DiscoveryNode("data", "data", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
|
= new DiscoveryNode("data", "data", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
|
||||||
|
|
||||||
final ClusterState clusterState = ClusterState.builder(new ClusterName("cluster")).nodes(new Builder()
|
final ClusterState clusterState = ClusterState.builder(new ClusterName("cluster")).nodes(new Builder()
|
||||||
.add(localNode).add(otherNode1).add(otherNode2).add(otherDataNode).localNodeId(localNode.getId())).build();
|
.add(localNode).add(otherNode1).add(otherNode2).add(otherDataNode).localNodeId(localNode.getId())).build();
|
||||||
|
|
||||||
assertThat(makeRequest().resolveVotingTombstones(clusterState),
|
assertThat(makeRequest().resolveVotingConfigExclusions(clusterState),
|
||||||
containsInAnyOrder(localNodeTombstone, otherNode1Tombstone, otherNode2Tombstone));
|
containsInAnyOrder(localNodeExclusion, otherNode1Exclusion, otherNode2Exclusion));
|
||||||
assertThat(makeRequest("_all").resolveVotingTombstones(clusterState),
|
assertThat(makeRequest("_all").resolveVotingConfigExclusions(clusterState),
|
||||||
containsInAnyOrder(localNodeTombstone, otherNode1Tombstone, otherNode2Tombstone));
|
containsInAnyOrder(localNodeExclusion, otherNode1Exclusion, otherNode2Exclusion));
|
||||||
assertThat(makeRequest("_local").resolveVotingTombstones(clusterState),
|
assertThat(makeRequest("_local").resolveVotingConfigExclusions(clusterState),
|
||||||
contains(localNodeTombstone));
|
contains(localNodeExclusion));
|
||||||
assertThat(makeRequest("other*").resolveVotingTombstones(clusterState),
|
assertThat(makeRequest("other*").resolveVotingConfigExclusions(clusterState),
|
||||||
containsInAnyOrder(otherNode1Tombstone, otherNode2Tombstone));
|
containsInAnyOrder(otherNode1Exclusion, otherNode2Exclusion));
|
||||||
|
|
||||||
assertThat(expectThrows(IllegalArgumentException.class,
|
assertThat(expectThrows(IllegalArgumentException.class,
|
||||||
() -> makeRequest("not-a-node").resolveVotingTombstones(clusterState)).getMessage(),
|
() -> makeRequest("not-a-node").resolveVotingConfigExclusions(clusterState)).getMessage(),
|
||||||
equalTo("add voting tombstones request for [not-a-node] matched no master-eligible nodes"));
|
equalTo("add voting config exclusions request for [not-a-node] matched no master-eligible nodes"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testResolveAndCheckMaximum() {
|
public void testResolveAndCheckMaximum() {
|
||||||
final DiscoveryNode localNode
|
final DiscoveryNode localNode
|
||||||
= new DiscoveryNode("local", "local", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
= new DiscoveryNode("local", "local", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
||||||
final VotingTombstone localNodeTombstone = new VotingTombstone(localNode);
|
final VotingConfigExclusion localNodeExclusion = new VotingConfigExclusion(localNode);
|
||||||
final DiscoveryNode otherNode1
|
final DiscoveryNode otherNode1
|
||||||
= new DiscoveryNode("other1", "other1", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
= new DiscoveryNode("other1", "other1", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
||||||
final VotingTombstone otherNode1Tombstone = new VotingTombstone(otherNode1);
|
final VotingConfigExclusion otherNode1Exclusion = new VotingConfigExclusion(otherNode1);
|
||||||
final DiscoveryNode otherNode2
|
final DiscoveryNode otherNode2
|
||||||
= new DiscoveryNode("other2", "other2", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
= new DiscoveryNode("other2", "other2", buildNewFakeTransportAddress(), emptyMap(), singleton(Role.MASTER), Version.CURRENT);
|
||||||
final VotingTombstone otherNode2Tombstone = new VotingTombstone(otherNode2);
|
final VotingConfigExclusion otherNode2Exclusion = new VotingConfigExclusion(otherNode2);
|
||||||
|
|
||||||
final ClusterState.Builder builder = ClusterState.builder(new ClusterName("cluster")).nodes(new Builder()
|
final ClusterState.Builder builder = ClusterState.builder(new ClusterName("cluster")).nodes(new Builder()
|
||||||
.add(localNode).add(otherNode1).add(otherNode2).localNodeId(localNode.getId()));
|
.add(localNode).add(otherNode1).add(otherNode2).localNodeId(localNode.getId()));
|
||||||
builder.metaData(MetaData.builder()
|
builder.metaData(MetaData.builder()
|
||||||
.coordinationMetaData(CoordinationMetaData.builder().addVotingTombstone(otherNode1Tombstone).build()));
|
.coordinationMetaData(CoordinationMetaData.builder().addVotingConfigExclusion(otherNode1Exclusion).build()));
|
||||||
final ClusterState clusterState = builder.build();
|
final ClusterState clusterState = builder.build();
|
||||||
|
|
||||||
assertThat(makeRequest().resolveVotingTombstonesAndCheckMaximum(clusterState, 3, "setting.name"),
|
assertThat(makeRequest().resolveVotingConfigExclusionsAndCheckMaximum(clusterState, 3, "setting.name"),
|
||||||
containsInAnyOrder(localNodeTombstone, otherNode2Tombstone));
|
containsInAnyOrder(localNodeExclusion, otherNode2Exclusion));
|
||||||
assertThat(makeRequest("_local").resolveVotingTombstonesAndCheckMaximum(clusterState, 2, "setting.name"),
|
assertThat(makeRequest("_local").resolveVotingConfigExclusionsAndCheckMaximum(clusterState, 2, "setting.name"),
|
||||||
contains(localNodeTombstone));
|
contains(localNodeExclusion));
|
||||||
|
|
||||||
assertThat(expectThrows(IllegalArgumentException.class,
|
assertThat(expectThrows(IllegalArgumentException.class,
|
||||||
() -> makeRequest().resolveVotingTombstonesAndCheckMaximum(clusterState, 2, "setting.name")).getMessage(),
|
() -> makeRequest().resolveVotingConfigExclusionsAndCheckMaximum(clusterState, 2, "setting.name")).getMessage(),
|
||||||
equalTo("add voting tombstones request for [] would add [2] voting tombstones to the existing [1] which would exceed the " +
|
equalTo("add voting config exclusions request for [] would add [2] exclusions to the existing [1] which would exceed " +
|
||||||
"maximum of [2] set by [setting.name]"));
|
"the maximum of [2] set by [setting.name]"));
|
||||||
assertThat(expectThrows(IllegalArgumentException.class,
|
assertThat(expectThrows(IllegalArgumentException.class,
|
||||||
() -> makeRequest("_local").resolveVotingTombstonesAndCheckMaximum(clusterState, 1, "setting.name")).getMessage(),
|
() -> makeRequest("_local").resolveVotingConfigExclusionsAndCheckMaximum(clusterState, 1, "setting.name")).getMessage(),
|
||||||
equalTo("add voting tombstones request for [_local] would add [1] voting tombstones to the existing [1] which would exceed " +
|
equalTo("add voting config exclusions request for [_local] would add [1] exclusions to the existing [1] which would " +
|
||||||
"the maximum of [1] set by [setting.name]"));
|
"exceed the maximum of [1] set by [setting.name]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AddVotingTombstonesRequest makeRequest(String... descriptions) {
|
private static AddVotingConfigExclusionsRequest makeRequest(String... descriptions) {
|
||||||
return new AddVotingTombstonesRequest(descriptions);
|
return new AddVotingConfigExclusionsRequest(descriptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,10 +22,10 @@ import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class AddVotingTombstonesResponseTests extends ESTestCase {
|
public class AddVotingConfigExclusionsResponseTests extends ESTestCase {
|
||||||
public void testSerialization() throws IOException {
|
public void testSerialization() throws IOException {
|
||||||
final AddVotingTombstonesResponse originalRequest = new AddVotingTombstonesResponse();
|
final AddVotingConfigExclusionsResponse originalRequest = new AddVotingConfigExclusionsResponse();
|
||||||
copyWriteable(originalRequest, writableRegistry(), AddVotingTombstonesResponse::new);
|
copyWriteable(originalRequest, writableRegistry(), AddVotingConfigExclusionsResponse::new);
|
||||||
// there are no fields so we're just checking that this doesn't throw anything
|
// there are no fields so we're just checking that this doesn't throw anything
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -25,17 +25,17 @@ import java.io.IOException;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
public class ClearVotingTombstonesRequestTests extends ESTestCase {
|
public class ClearVotingConfigExclusionsRequestTests extends ESTestCase {
|
||||||
public void testSerialization() throws IOException {
|
public void testSerialization() throws IOException {
|
||||||
final ClearVotingTombstonesRequest originalRequest = new ClearVotingTombstonesRequest();
|
final ClearVotingConfigExclusionsRequest originalRequest = new ClearVotingConfigExclusionsRequest();
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
originalRequest.setWaitForRemoval(randomBoolean());
|
originalRequest.setWaitForRemoval(randomBoolean());
|
||||||
}
|
}
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
originalRequest.setTimeout(TimeValue.timeValueMillis(randomLongBetween(0, 30000)));
|
originalRequest.setTimeout(TimeValue.timeValueMillis(randomLongBetween(0, 30000)));
|
||||||
}
|
}
|
||||||
final ClearVotingTombstonesRequest deserialized
|
final ClearVotingConfigExclusionsRequest deserialized
|
||||||
= copyWriteable(originalRequest, writableRegistry(), ClearVotingTombstonesRequest::new);
|
= copyWriteable(originalRequest, writableRegistry(), ClearVotingConfigExclusionsRequest::new);
|
||||||
assertThat(deserialized.getWaitForRemoval(), equalTo(originalRequest.getWaitForRemoval()));
|
assertThat(deserialized.getWaitForRemoval(), equalTo(originalRequest.getWaitForRemoval()));
|
||||||
assertThat(deserialized.getTimeout(), equalTo(originalRequest.getTimeout()));
|
assertThat(deserialized.getTimeout(), equalTo(originalRequest.getTimeout()));
|
||||||
}
|
}
|
|
@ -22,10 +22,10 @@ import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class ClearVotingTombstonesResponseTests extends ESTestCase {
|
public class ClearVotingConfigExclusionsResponseTests extends ESTestCase {
|
||||||
public void testSerialization() throws IOException {
|
public void testSerialization() throws IOException {
|
||||||
final ClearVotingTombstonesResponse originalRequest = new ClearVotingTombstonesResponse();
|
final ClearVotingConfigExclusionsResponse originalRequest = new ClearVotingConfigExclusionsResponse();
|
||||||
copyWriteable(originalRequest, writableRegistry(), ClearVotingTombstonesResponse::new);
|
copyWriteable(originalRequest, writableRegistry(), ClearVotingConfigExclusionsResponse::new);
|
||||||
// there are no fields so we're just checking that this doesn't throw anything
|
// there are no fields so we're just checking that this doesn't throw anything
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@ import org.elasticsearch.cluster.ClusterStateObserver.Listener;
|
||||||
import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||||
|
@ -61,7 +61,7 @@ import java.util.function.Consumer;
|
||||||
import static java.util.Collections.emptyMap;
|
import static java.util.Collections.emptyMap;
|
||||||
import static java.util.Collections.emptySet;
|
import static java.util.Collections.emptySet;
|
||||||
import static java.util.Collections.singleton;
|
import static java.util.Collections.singleton;
|
||||||
import static org.elasticsearch.action.admin.cluster.configuration.TransportAddVotingTombstonesAction.MAXIMUM_VOTING_TOMBSTONES_SETTING;
|
import static org.elasticsearch.action.admin.cluster.configuration.TransportAddVotingConfigExclusionsAction.MAXIMUM_VOTING_CONFIG_EXCLUSIONS_SETTING;
|
||||||
import static org.elasticsearch.cluster.ClusterState.builder;
|
import static org.elasticsearch.cluster.ClusterState.builder;
|
||||||
import static org.elasticsearch.test.ClusterServiceUtils.createClusterService;
|
import static org.elasticsearch.test.ClusterServiceUtils.createClusterService;
|
||||||
import static org.elasticsearch.test.ClusterServiceUtils.setState;
|
import static org.elasticsearch.test.ClusterServiceUtils.setState;
|
||||||
|
@ -72,12 +72,12 @@ import static org.hamcrest.Matchers.instanceOf;
|
||||||
import static org.hamcrest.Matchers.sameInstance;
|
import static org.hamcrest.Matchers.sameInstance;
|
||||||
import static org.hamcrest.Matchers.startsWith;
|
import static org.hamcrest.Matchers.startsWith;
|
||||||
|
|
||||||
public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
public class TransportAddVotingConfigExclusionsActionTests extends ESTestCase {
|
||||||
|
|
||||||
private static ThreadPool threadPool;
|
private static ThreadPool threadPool;
|
||||||
private static ClusterService clusterService;
|
private static ClusterService clusterService;
|
||||||
private static DiscoveryNode localNode, otherNode1, otherNode2, otherDataNode;
|
private static DiscoveryNode localNode, otherNode1, otherNode2, otherDataNode;
|
||||||
private static VotingTombstone localNodeTombstone, otherNode1Tombstone, otherNode2Tombstone;
|
private static VotingConfigExclusion localNodeExclusion, otherNode1Exclusion, otherNode2Exclusion;
|
||||||
|
|
||||||
private TransportService transportService;
|
private TransportService transportService;
|
||||||
private ClusterStateObserver clusterStateObserver;
|
private ClusterStateObserver clusterStateObserver;
|
||||||
|
@ -86,11 +86,11 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
public static void createThreadPoolAndClusterService() {
|
public static void createThreadPoolAndClusterService() {
|
||||||
threadPool = new TestThreadPool("test", Settings.EMPTY);
|
threadPool = new TestThreadPool("test", Settings.EMPTY);
|
||||||
localNode = makeDiscoveryNode("local");
|
localNode = makeDiscoveryNode("local");
|
||||||
localNodeTombstone = new VotingTombstone(localNode);
|
localNodeExclusion = new VotingConfigExclusion(localNode);
|
||||||
otherNode1 = makeDiscoveryNode("other1");
|
otherNode1 = makeDiscoveryNode("other1");
|
||||||
otherNode1Tombstone = new VotingTombstone(otherNode1);
|
otherNode1Exclusion = new VotingConfigExclusion(otherNode1);
|
||||||
otherNode2 = makeDiscoveryNode("other2");
|
otherNode2 = makeDiscoveryNode("other2");
|
||||||
otherNode2Tombstone = new VotingTombstone(otherNode2);
|
otherNode2Exclusion = new VotingConfigExclusion(otherNode2);
|
||||||
otherDataNode = new DiscoveryNode("data", "data", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
|
otherDataNode = new DiscoveryNode("data", "data", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
|
||||||
clusterService = createClusterService(threadPool, localNode);
|
clusterService = createClusterService(threadPool, localNode);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
transportService = transport.createTransportService(Settings.EMPTY, threadPool,
|
transportService = transport.createTransportService(Settings.EMPTY, threadPool,
|
||||||
TransportService.NOOP_TRANSPORT_INTERCEPTOR, boundTransportAddress -> localNode, null, emptySet());
|
TransportService.NOOP_TRANSPORT_INTERCEPTOR, boundTransportAddress -> localNode, null, emptySet());
|
||||||
|
|
||||||
new TransportAddVotingTombstonesAction(transportService, clusterService, threadPool, new ActionFilters(emptySet()),
|
new TransportAddVotingConfigExclusionsAction(transportService, clusterService, threadPool, new ActionFilters(emptySet()),
|
||||||
new IndexNameExpressionResolver()); // registers action
|
new IndexNameExpressionResolver()); // registers action
|
||||||
|
|
||||||
transportService.start();
|
transportService.start();
|
||||||
|
@ -132,9 +132,9 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
public void testWithdrawsVoteFromANode() throws InterruptedException {
|
public void testWithdrawsVoteFromANode() throws InterruptedException {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
clusterStateObserver.waitForNextChange(new AdjustConfigurationForTombstones());
|
clusterStateObserver.waitForNextChange(new AdjustConfigurationForExclusions());
|
||||||
transportService.sendRequest(localNode, AddVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, AddVotingConfigExclusionsAction.NAME,
|
||||||
new AddVotingTombstonesRequest(new String[]{"other1"}),
|
new AddVotingConfigExclusionsRequest(new String[]{"other1"}),
|
||||||
expectSuccess(r -> {
|
expectSuccess(r -> {
|
||||||
assertNotNull(r);
|
assertNotNull(r);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -142,15 +142,15 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
assertThat(clusterService.getClusterApplierService().state().getVotingTombstones(), contains(otherNode1Tombstone));
|
assertThat(clusterService.getClusterApplierService().state().getVotingConfigExclusions(), contains(otherNode1Exclusion));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWithdrawsVotesFromMultipleNodes() throws InterruptedException {
|
public void testWithdrawsVotesFromMultipleNodes() throws InterruptedException {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
clusterStateObserver.waitForNextChange(new AdjustConfigurationForTombstones());
|
clusterStateObserver.waitForNextChange(new AdjustConfigurationForExclusions());
|
||||||
transportService.sendRequest(localNode, AddVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, AddVotingConfigExclusionsAction.NAME,
|
||||||
new AddVotingTombstonesRequest(new String[]{"other1", "other2"}),
|
new AddVotingConfigExclusionsRequest(new String[]{"other1", "other2"}),
|
||||||
expectSuccess(r -> {
|
expectSuccess(r -> {
|
||||||
assertNotNull(r);
|
assertNotNull(r);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -158,16 +158,16 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
assertThat(clusterService.getClusterApplierService().state().getVotingTombstones(),
|
assertThat(clusterService.getClusterApplierService().state().getVotingConfigExclusions(),
|
||||||
containsInAnyOrder(otherNode1Tombstone, otherNode2Tombstone));
|
containsInAnyOrder(otherNode1Exclusion, otherNode2Exclusion));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWithdrawsVotesFromNodesMatchingWildcard() throws InterruptedException {
|
public void testWithdrawsVotesFromNodesMatchingWildcard() throws InterruptedException {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
clusterStateObserver.waitForNextChange(new AdjustConfigurationForTombstones());
|
clusterStateObserver.waitForNextChange(new AdjustConfigurationForExclusions());
|
||||||
transportService.sendRequest(localNode, AddVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, AddVotingConfigExclusionsAction.NAME,
|
||||||
new AddVotingTombstonesRequest(new String[]{"other*"}),
|
new AddVotingConfigExclusionsRequest(new String[]{"other*"}),
|
||||||
expectSuccess(r -> {
|
expectSuccess(r -> {
|
||||||
assertNotNull(r);
|
assertNotNull(r);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -175,16 +175,16 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
assertThat(clusterService.getClusterApplierService().state().getVotingTombstones(),
|
assertThat(clusterService.getClusterApplierService().state().getVotingConfigExclusions(),
|
||||||
containsInAnyOrder(otherNode1Tombstone, otherNode2Tombstone));
|
containsInAnyOrder(otherNode1Exclusion, otherNode2Exclusion));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWithdrawsVotesFromAllMasterEligibleNodes() throws InterruptedException {
|
public void testWithdrawsVotesFromAllMasterEligibleNodes() throws InterruptedException {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
clusterStateObserver.waitForNextChange(new AdjustConfigurationForTombstones());
|
clusterStateObserver.waitForNextChange(new AdjustConfigurationForExclusions());
|
||||||
transportService.sendRequest(localNode, AddVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, AddVotingConfigExclusionsAction.NAME,
|
||||||
new AddVotingTombstonesRequest(new String[]{"_all"}),
|
new AddVotingConfigExclusionsRequest(new String[]{"_all"}),
|
||||||
expectSuccess(r -> {
|
expectSuccess(r -> {
|
||||||
assertNotNull(r);
|
assertNotNull(r);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -192,16 +192,16 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
assertThat(clusterService.getClusterApplierService().state().getVotingTombstones(),
|
assertThat(clusterService.getClusterApplierService().state().getVotingConfigExclusions(),
|
||||||
containsInAnyOrder(localNodeTombstone, otherNode1Tombstone, otherNode2Tombstone));
|
containsInAnyOrder(localNodeExclusion, otherNode1Exclusion, otherNode2Exclusion));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWithdrawsVoteFromLocalNode() throws InterruptedException {
|
public void testWithdrawsVoteFromLocalNode() throws InterruptedException {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
clusterStateObserver.waitForNextChange(new AdjustConfigurationForTombstones());
|
clusterStateObserver.waitForNextChange(new AdjustConfigurationForExclusions());
|
||||||
transportService.sendRequest(localNode, AddVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, AddVotingConfigExclusionsAction.NAME,
|
||||||
new AddVotingTombstonesRequest(new String[]{"_local"}),
|
new AddVotingConfigExclusionsRequest(new String[]{"_local"}),
|
||||||
expectSuccess(r -> {
|
expectSuccess(r -> {
|
||||||
assertNotNull(r);
|
assertNotNull(r);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -209,8 +209,8 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
assertThat(clusterService.getClusterApplierService().state().getVotingTombstones(),
|
assertThat(clusterService.getClusterApplierService().state().getVotingConfigExclusions(),
|
||||||
contains(localNodeTombstone));
|
contains(localNodeExclusion));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReturnsImmediatelyIfVoteAlreadyWithdrawn() throws InterruptedException {
|
public void testReturnsImmediatelyIfVoteAlreadyWithdrawn() throws InterruptedException {
|
||||||
|
@ -225,8 +225,8 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
// no observer to reconfigure
|
// no observer to reconfigure
|
||||||
transportService.sendRequest(localNode, AddVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, AddVotingConfigExclusionsAction.NAME,
|
||||||
new AddVotingTombstonesRequest(new String[]{"other1"}, TimeValue.ZERO),
|
new AddVotingConfigExclusionsRequest(new String[]{"other1"}, TimeValue.ZERO),
|
||||||
expectSuccess(r -> {
|
expectSuccess(r -> {
|
||||||
assertNotNull(r);
|
assertNotNull(r);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -234,34 +234,16 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
assertThat(clusterService.getClusterApplierService().state().getVotingTombstones(),
|
assertThat(clusterService.getClusterApplierService().state().getVotingConfigExclusions(),
|
||||||
contains(otherNode1Tombstone));
|
contains(otherNode1Exclusion));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReturnsErrorIfNoMatchingNodes() throws InterruptedException {
|
public void testReturnsErrorIfNoMatchingNodes() throws InterruptedException {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
final SetOnce<TransportException> exceptionHolder = new SetOnce<>();
|
final SetOnce<TransportException> exceptionHolder = new SetOnce<>();
|
||||||
|
|
||||||
transportService.sendRequest(localNode, AddVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, AddVotingConfigExclusionsAction.NAME,
|
||||||
new AddVotingTombstonesRequest(new String[]{"not-a-node"}),
|
new AddVotingConfigExclusionsRequest(new String[]{"not-a-node"}),
|
||||||
expectError(e -> {
|
|
||||||
exceptionHolder.set(e);
|
|
||||||
countDownLatch.countDown();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
|
||||||
final Throwable rootCause = exceptionHolder.get().getRootCause();
|
|
||||||
assertThat(rootCause, instanceOf(IllegalArgumentException.class));
|
|
||||||
assertThat(rootCause.getMessage(), equalTo("add voting tombstones request for [not-a-node] matched no master-eligible nodes"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testOnlyMatchesMasterEligibleNodes() throws InterruptedException {
|
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
|
||||||
final SetOnce<TransportException> exceptionHolder = new SetOnce<>();
|
|
||||||
|
|
||||||
transportService.sendRequest(localNode, AddVotingTombstonesAction.NAME,
|
|
||||||
new AddVotingTombstonesRequest(new String[]{"_all", "master:false"}),
|
|
||||||
expectError(e -> {
|
expectError(e -> {
|
||||||
exceptionHolder.set(e);
|
exceptionHolder.set(e);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -272,23 +254,42 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
final Throwable rootCause = exceptionHolder.get().getRootCause();
|
final Throwable rootCause = exceptionHolder.get().getRootCause();
|
||||||
assertThat(rootCause, instanceOf(IllegalArgumentException.class));
|
assertThat(rootCause, instanceOf(IllegalArgumentException.class));
|
||||||
assertThat(rootCause.getMessage(),
|
assertThat(rootCause.getMessage(),
|
||||||
equalTo("add voting tombstones request for [_all, master:false] matched no master-eligible nodes"));
|
equalTo("add voting config exclusions request for [not-a-node] matched no master-eligible nodes"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSucceedsEvenIfAllTombstonesAlreadyAdded() throws InterruptedException {
|
public void testOnlyMatchesMasterEligibleNodes() throws InterruptedException {
|
||||||
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
final SetOnce<TransportException> exceptionHolder = new SetOnce<>();
|
||||||
|
|
||||||
|
transportService.sendRequest(localNode, AddVotingConfigExclusionsAction.NAME,
|
||||||
|
new AddVotingConfigExclusionsRequest(new String[]{"_all", "master:false"}),
|
||||||
|
expectError(e -> {
|
||||||
|
exceptionHolder.set(e);
|
||||||
|
countDownLatch.countDown();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
|
final Throwable rootCause = exceptionHolder.get().getRootCause();
|
||||||
|
assertThat(rootCause, instanceOf(IllegalArgumentException.class));
|
||||||
|
assertThat(rootCause.getMessage(),
|
||||||
|
equalTo("add voting config exclusions request for [_all, master:false] matched no master-eligible nodes"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSucceedsEvenIfAllExclusionsAlreadyAdded() throws InterruptedException {
|
||||||
final ClusterState state = clusterService.state();
|
final ClusterState state = clusterService.state();
|
||||||
final ClusterState.Builder builder = builder(state);
|
final ClusterState.Builder builder = builder(state);
|
||||||
builder.metaData(MetaData.builder(state.metaData()).
|
builder.metaData(MetaData.builder(state.metaData()).
|
||||||
coordinationMetaData(
|
coordinationMetaData(
|
||||||
CoordinationMetaData.builder(state.coordinationMetaData())
|
CoordinationMetaData.builder(state.coordinationMetaData())
|
||||||
.addVotingTombstone(otherNode1Tombstone).
|
.addVotingConfigExclusion(otherNode1Exclusion).
|
||||||
build()));
|
build()));
|
||||||
setState(clusterService, builder);
|
setState(clusterService, builder);
|
||||||
|
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
transportService.sendRequest(localNode, AddVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, AddVotingConfigExclusionsAction.NAME,
|
||||||
new AddVotingTombstonesRequest(new String[]{"other1"}),
|
new AddVotingConfigExclusionsRequest(new String[]{"other1"}),
|
||||||
expectSuccess(r -> {
|
expectSuccess(r -> {
|
||||||
assertNotNull(r);
|
assertNotNull(r);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -296,21 +297,21 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
assertThat(clusterService.getClusterApplierService().state().getVotingTombstones(),
|
assertThat(clusterService.getClusterApplierService().state().getVotingConfigExclusions(),
|
||||||
contains(otherNode1Tombstone));
|
contains(otherNode1Exclusion));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReturnsErrorIfMaximumTombstoneCountExceeded() throws InterruptedException {
|
public void testReturnsErrorIfMaximumExclusionCountExceeded() throws InterruptedException {
|
||||||
final MetaData.Builder metaDataBuilder = MetaData.builder(clusterService.state().metaData()).persistentSettings(
|
final MetaData.Builder metaDataBuilder = MetaData.builder(clusterService.state().metaData()).persistentSettings(
|
||||||
Settings.builder().put(clusterService.state().metaData().persistentSettings())
|
Settings.builder().put(clusterService.state().metaData().persistentSettings())
|
||||||
.put(MAXIMUM_VOTING_TOMBSTONES_SETTING.getKey(), 2).build());
|
.put(MAXIMUM_VOTING_CONFIG_EXCLUSIONS_SETTING.getKey(), 2).build());
|
||||||
CoordinationMetaData.Builder coordinationMetaDataBuilder =
|
CoordinationMetaData.Builder coordinationMetaDataBuilder =
|
||||||
CoordinationMetaData.builder(clusterService.state().coordinationMetaData())
|
CoordinationMetaData.builder(clusterService.state().coordinationMetaData())
|
||||||
.addVotingTombstone(localNodeTombstone);
|
.addVotingConfigExclusion(localNodeExclusion);
|
||||||
|
|
||||||
final int existingCount, newCount;
|
final int existingCount, newCount;
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
coordinationMetaDataBuilder.addVotingTombstone(otherNode1Tombstone);
|
coordinationMetaDataBuilder.addVotingConfigExclusion(otherNode1Exclusion);
|
||||||
existingCount = 2;
|
existingCount = 2;
|
||||||
newCount = 1;
|
newCount = 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -326,8 +327,8 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
final SetOnce<TransportException> exceptionHolder = new SetOnce<>();
|
final SetOnce<TransportException> exceptionHolder = new SetOnce<>();
|
||||||
|
|
||||||
transportService.sendRequest(localNode, AddVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, AddVotingConfigExclusionsAction.NAME,
|
||||||
new AddVotingTombstonesRequest(new String[]{"other*"}),
|
new AddVotingConfigExclusionsRequest(new String[]{"other*"}),
|
||||||
expectError(e -> {
|
expectError(e -> {
|
||||||
exceptionHolder.set(e);
|
exceptionHolder.set(e);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -337,17 +338,17 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
final Throwable rootCause = exceptionHolder.get().getRootCause();
|
final Throwable rootCause = exceptionHolder.get().getRootCause();
|
||||||
assertThat(rootCause, instanceOf(IllegalArgumentException.class));
|
assertThat(rootCause, instanceOf(IllegalArgumentException.class));
|
||||||
assertThat(rootCause.getMessage(), equalTo("add voting tombstones request for [other*] would add [" + newCount +
|
assertThat(rootCause.getMessage(), equalTo("add voting config exclusions request for [other*] would add [" + newCount +
|
||||||
"] voting tombstones to the existing [" + existingCount +
|
"] exclusions to the existing [" + existingCount +
|
||||||
"] which would exceed the maximum of [2] set by [cluster.max_voting_tombstones]"));
|
"] which would exceed the maximum of [2] set by [cluster.max_voting_config_exclusions]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTimesOut() throws InterruptedException {
|
public void testTimesOut() throws InterruptedException {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
final SetOnce<TransportException> exceptionHolder = new SetOnce<>();
|
final SetOnce<TransportException> exceptionHolder = new SetOnce<>();
|
||||||
|
|
||||||
transportService.sendRequest(localNode, AddVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, AddVotingConfigExclusionsAction.NAME,
|
||||||
new AddVotingTombstonesRequest(new String[]{"other1"}, TimeValue.timeValueMillis(100)),
|
new AddVotingConfigExclusionsRequest(new String[]{"other1"}, TimeValue.timeValueMillis(100)),
|
||||||
expectError(e -> {
|
expectError(e -> {
|
||||||
exceptionHolder.set(e);
|
exceptionHolder.set(e);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -357,26 +358,27 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
final Throwable rootCause = exceptionHolder.get().getRootCause();
|
final Throwable rootCause = exceptionHolder.get().getRootCause();
|
||||||
assertThat(rootCause,instanceOf(ElasticsearchTimeoutException.class));
|
assertThat(rootCause,instanceOf(ElasticsearchTimeoutException.class));
|
||||||
assertThat(rootCause.getMessage(), startsWith("timed out waiting for withdrawal of votes from [{other1}"));
|
assertThat(rootCause.getMessage(), startsWith("timed out waiting for voting config exclusions [{other1}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransportResponseHandler<AddVotingTombstonesResponse> expectSuccess(Consumer<AddVotingTombstonesResponse> onResponse) {
|
private TransportResponseHandler<AddVotingConfigExclusionsResponse> expectSuccess(
|
||||||
|
Consumer<AddVotingConfigExclusionsResponse> onResponse) {
|
||||||
return responseHandler(onResponse, e -> {
|
return responseHandler(onResponse, e -> {
|
||||||
throw new AssertionError("unexpected", e);
|
throw new AssertionError("unexpected", e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransportResponseHandler<AddVotingTombstonesResponse> expectError(Consumer<TransportException> onException) {
|
private TransportResponseHandler<AddVotingConfigExclusionsResponse> expectError(Consumer<TransportException> onException) {
|
||||||
return responseHandler(r -> {
|
return responseHandler(r -> {
|
||||||
assert false : r;
|
assert false : r;
|
||||||
}, onException);
|
}, onException);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransportResponseHandler<AddVotingTombstonesResponse> responseHandler(Consumer<AddVotingTombstonesResponse> onResponse,
|
private TransportResponseHandler<AddVotingConfigExclusionsResponse> responseHandler(
|
||||||
Consumer<TransportException> onException) {
|
Consumer<AddVotingConfigExclusionsResponse> onResponse, Consumer<TransportException> onException) {
|
||||||
return new TransportResponseHandler<AddVotingTombstonesResponse>() {
|
return new TransportResponseHandler<AddVotingConfigExclusionsResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void handleResponse(AddVotingTombstonesResponse response) {
|
public void handleResponse(AddVotingConfigExclusionsResponse response) {
|
||||||
onResponse.accept(response);
|
onResponse.accept(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,13 +393,13 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AddVotingTombstonesResponse read(StreamInput in) throws IOException {
|
public AddVotingConfigExclusionsResponse read(StreamInput in) throws IOException {
|
||||||
return new AddVotingTombstonesResponse(in);
|
return new AddVotingConfigExclusionsResponse(in);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AdjustConfigurationForTombstones implements Listener {
|
private class AdjustConfigurationForExclusions implements Listener {
|
||||||
@Override
|
@Override
|
||||||
public void onNewClusterState(ClusterState state) {
|
public void onNewClusterState(ClusterState state) {
|
||||||
clusterService.getMasterService().submitStateUpdateTask("reconfiguration", new ClusterStateUpdateTask() {
|
clusterService.getMasterService().submitStateUpdateTask("reconfiguration", new ClusterStateUpdateTask() {
|
||||||
|
@ -406,7 +408,7 @@ public class TransportAddVotingTombstonesActionTests extends ESTestCase {
|
||||||
assertThat(currentState, sameInstance(state));
|
assertThat(currentState, sameInstance(state));
|
||||||
final Set<String> votingNodeIds = new HashSet<>();
|
final Set<String> votingNodeIds = new HashSet<>();
|
||||||
currentState.nodes().forEach(n -> votingNodeIds.add(n.getId()));
|
currentState.nodes().forEach(n -> votingNodeIds.add(n.getId()));
|
||||||
currentState.getVotingTombstones().forEach(t -> votingNodeIds.remove(t.getNodeId()));
|
currentState.getVotingConfigExclusions().forEach(t -> votingNodeIds.remove(t.getNodeId()));
|
||||||
final VotingConfiguration votingConfiguration = new VotingConfiguration(votingNodeIds);
|
final VotingConfiguration votingConfiguration = new VotingConfiguration(votingNodeIds);
|
||||||
return builder(currentState)
|
return builder(currentState)
|
||||||
.metaData(MetaData.builder(currentState.metaData())
|
.metaData(MetaData.builder(currentState.metaData())
|
|
@ -25,7 +25,7 @@ import org.elasticsearch.action.support.ActionFilters;
|
||||||
import org.elasticsearch.cluster.ClusterName;
|
import org.elasticsearch.cluster.ClusterName;
|
||||||
import org.elasticsearch.cluster.ClusterState;
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||||
|
@ -62,12 +62,12 @@ import static org.hamcrest.Matchers.empty;
|
||||||
import static org.hamcrest.Matchers.instanceOf;
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
import static org.hamcrest.Matchers.startsWith;
|
import static org.hamcrest.Matchers.startsWith;
|
||||||
|
|
||||||
public class TransportClearVotingTombstonesActionTests extends ESTestCase {
|
public class TransportClearVotingConfigExclusionsActionTests extends ESTestCase {
|
||||||
|
|
||||||
private static ThreadPool threadPool;
|
private static ThreadPool threadPool;
|
||||||
private static ClusterService clusterService;
|
private static ClusterService clusterService;
|
||||||
private static DiscoveryNode localNode, otherNode1, otherNode2;
|
private static DiscoveryNode localNode, otherNode1, otherNode2;
|
||||||
private static VotingTombstone otherNode1Tombstone, otherNode2Tombstone;
|
private static VotingConfigExclusion otherNode1Exclusion, otherNode2Exclusion;
|
||||||
|
|
||||||
private TransportService transportService;
|
private TransportService transportService;
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ public class TransportClearVotingTombstonesActionTests extends ESTestCase {
|
||||||
threadPool = new TestThreadPool("test", Settings.EMPTY);
|
threadPool = new TestThreadPool("test", Settings.EMPTY);
|
||||||
localNode = new DiscoveryNode("local", buildNewFakeTransportAddress(), Version.CURRENT);
|
localNode = new DiscoveryNode("local", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||||
otherNode1 = new DiscoveryNode("other1", "other1", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
|
otherNode1 = new DiscoveryNode("other1", "other1", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
|
||||||
otherNode1Tombstone = new VotingTombstone(otherNode1);
|
otherNode1Exclusion = new VotingConfigExclusion(otherNode1);
|
||||||
otherNode2 = new DiscoveryNode("other2", "other2", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
|
otherNode2 = new DiscoveryNode("other2", "other2", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
|
||||||
otherNode2Tombstone = new VotingTombstone(otherNode2);
|
otherNode2Exclusion = new VotingConfigExclusion(otherNode2);
|
||||||
clusterService = createClusterService(threadPool, localNode);
|
clusterService = createClusterService(threadPool, localNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ public class TransportClearVotingTombstonesActionTests extends ESTestCase {
|
||||||
transportService = transport.createTransportService(Settings.EMPTY, threadPool,
|
transportService = transport.createTransportService(Settings.EMPTY, threadPool,
|
||||||
TransportService.NOOP_TRANSPORT_INTERCEPTOR, boundTransportAddress -> localNode, null, emptySet());
|
TransportService.NOOP_TRANSPORT_INTERCEPTOR, boundTransportAddress -> localNode, null, emptySet());
|
||||||
|
|
||||||
new TransportClearVotingTombstonesAction(transportService, clusterService, threadPool, new ActionFilters(emptySet()),
|
new TransportClearVotingConfigExclusionsAction(transportService, clusterService, threadPool, new ActionFilters(emptySet()),
|
||||||
new IndexNameExpressionResolver()); // registers action
|
new IndexNameExpressionResolver()); // registers action
|
||||||
|
|
||||||
transportService.start();
|
transportService.start();
|
||||||
|
@ -105,20 +105,20 @@ public class TransportClearVotingTombstonesActionTests extends ESTestCase {
|
||||||
.localNodeId(localNode.getId()).masterNodeId(localNode.getId()));
|
.localNodeId(localNode.getId()).masterNodeId(localNode.getId()));
|
||||||
builder.metaData(MetaData.builder()
|
builder.metaData(MetaData.builder()
|
||||||
.coordinationMetaData(CoordinationMetaData.builder()
|
.coordinationMetaData(CoordinationMetaData.builder()
|
||||||
.addVotingTombstone(otherNode1Tombstone)
|
.addVotingConfigExclusion(otherNode1Exclusion)
|
||||||
.addVotingTombstone(otherNode2Tombstone)
|
.addVotingConfigExclusion(otherNode2Exclusion)
|
||||||
.build()));
|
.build()));
|
||||||
setState(clusterService, builder);
|
setState(clusterService, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testClearsVotingTombstones() throws InterruptedException {
|
public void testClearsVotingConfigExclusions() throws InterruptedException {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
final SetOnce<ClearVotingTombstonesResponse> responseHolder = new SetOnce<>();
|
final SetOnce<ClearVotingConfigExclusionsResponse> responseHolder = new SetOnce<>();
|
||||||
|
|
||||||
final ClearVotingTombstonesRequest clearVotingTombstonesRequest = new ClearVotingTombstonesRequest();
|
final ClearVotingConfigExclusionsRequest clearVotingConfigExclusionsRequest = new ClearVotingConfigExclusionsRequest();
|
||||||
clearVotingTombstonesRequest.setWaitForRemoval(false);
|
clearVotingConfigExclusionsRequest.setWaitForRemoval(false);
|
||||||
transportService.sendRequest(localNode, ClearVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, ClearVotingConfigExclusionsAction.NAME,
|
||||||
clearVotingTombstonesRequest,
|
clearVotingConfigExclusionsRequest,
|
||||||
expectSuccess(r -> {
|
expectSuccess(r -> {
|
||||||
responseHolder.set(r);
|
responseHolder.set(r);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -127,17 +127,17 @@ public class TransportClearVotingTombstonesActionTests extends ESTestCase {
|
||||||
|
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
assertNotNull(responseHolder.get());
|
assertNotNull(responseHolder.get());
|
||||||
assertThat(clusterService.getClusterApplierService().state().getVotingTombstones(), empty());
|
assertThat(clusterService.getClusterApplierService().state().getVotingConfigExclusions(), empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTimesOutIfWaitingForNodesThatAreNotRemoved() throws InterruptedException {
|
public void testTimesOutIfWaitingForNodesThatAreNotRemoved() throws InterruptedException {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
final SetOnce<TransportException> responseHolder = new SetOnce<>();
|
final SetOnce<TransportException> responseHolder = new SetOnce<>();
|
||||||
|
|
||||||
final ClearVotingTombstonesRequest clearVotingTombstonesRequest = new ClearVotingTombstonesRequest();
|
final ClearVotingConfigExclusionsRequest clearVotingConfigExclusionsRequest = new ClearVotingConfigExclusionsRequest();
|
||||||
clearVotingTombstonesRequest.setTimeout(TimeValue.timeValueMillis(100));
|
clearVotingConfigExclusionsRequest.setTimeout(TimeValue.timeValueMillis(100));
|
||||||
transportService.sendRequest(localNode, ClearVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, ClearVotingConfigExclusionsAction.NAME,
|
||||||
clearVotingTombstonesRequest,
|
clearVotingConfigExclusionsRequest,
|
||||||
expectError(e -> {
|
expectError(e -> {
|
||||||
responseHolder.set(e);
|
responseHolder.set(e);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -145,8 +145,8 @@ public class TransportClearVotingTombstonesActionTests extends ESTestCase {
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
assertThat(clusterService.getClusterApplierService().state().getVotingTombstones(),
|
assertThat(clusterService.getClusterApplierService().state().getVotingConfigExclusions(),
|
||||||
containsInAnyOrder(otherNode1Tombstone, otherNode2Tombstone));
|
containsInAnyOrder(otherNode1Exclusion, otherNode2Exclusion));
|
||||||
final Throwable rootCause = responseHolder.get().getRootCause();
|
final Throwable rootCause = responseHolder.get().getRootCause();
|
||||||
assertThat(rootCause, instanceOf(ElasticsearchTimeoutException.class));
|
assertThat(rootCause, instanceOf(ElasticsearchTimeoutException.class));
|
||||||
assertThat(rootCause.getMessage(),
|
assertThat(rootCause.getMessage(),
|
||||||
|
@ -155,10 +155,10 @@ public class TransportClearVotingTombstonesActionTests extends ESTestCase {
|
||||||
|
|
||||||
public void testSucceedsIfNodesAreRemovedWhileWaiting() throws InterruptedException {
|
public void testSucceedsIfNodesAreRemovedWhileWaiting() throws InterruptedException {
|
||||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
final SetOnce<ClearVotingTombstonesResponse> responseHolder = new SetOnce<>();
|
final SetOnce<ClearVotingConfigExclusionsResponse> responseHolder = new SetOnce<>();
|
||||||
|
|
||||||
transportService.sendRequest(localNode, ClearVotingTombstonesAction.NAME,
|
transportService.sendRequest(localNode, ClearVotingConfigExclusionsAction.NAME,
|
||||||
new ClearVotingTombstonesRequest(),
|
new ClearVotingConfigExclusionsRequest(),
|
||||||
expectSuccess(r -> {
|
expectSuccess(r -> {
|
||||||
responseHolder.set(r);
|
responseHolder.set(r);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
|
@ -170,26 +170,27 @@ public class TransportClearVotingTombstonesActionTests extends ESTestCase {
|
||||||
setState(clusterService, builder);
|
setState(clusterService, builder);
|
||||||
|
|
||||||
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
assertTrue(countDownLatch.await(30, TimeUnit.SECONDS));
|
||||||
assertThat(clusterService.getClusterApplierService().state().getVotingTombstones(), empty());
|
assertThat(clusterService.getClusterApplierService().state().getVotingConfigExclusions(), empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransportResponseHandler<ClearVotingTombstonesResponse> expectSuccess(Consumer<ClearVotingTombstonesResponse> onResponse) {
|
private TransportResponseHandler<ClearVotingConfigExclusionsResponse> expectSuccess(
|
||||||
|
Consumer<ClearVotingConfigExclusionsResponse> onResponse) {
|
||||||
return responseHandler(onResponse, e -> {
|
return responseHandler(onResponse, e -> {
|
||||||
throw new AssertionError("unexpected", e);
|
throw new AssertionError("unexpected", e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransportResponseHandler<ClearVotingTombstonesResponse> expectError(Consumer<TransportException> onException) {
|
private TransportResponseHandler<ClearVotingConfigExclusionsResponse> expectError(Consumer<TransportException> onException) {
|
||||||
return responseHandler(r -> {
|
return responseHandler(r -> {
|
||||||
assert false : r;
|
assert false : r;
|
||||||
}, onException);
|
}, onException);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransportResponseHandler<ClearVotingTombstonesResponse> responseHandler(Consumer<ClearVotingTombstonesResponse> onResponse,
|
private TransportResponseHandler<ClearVotingConfigExclusionsResponse> responseHandler(
|
||||||
Consumer<TransportException> onException) {
|
Consumer<ClearVotingConfigExclusionsResponse> onResponse, Consumer<TransportException> onException) {
|
||||||
return new TransportResponseHandler<ClearVotingTombstonesResponse>() {
|
return new TransportResponseHandler<ClearVotingConfigExclusionsResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void handleResponse(ClearVotingTombstonesResponse response) {
|
public void handleResponse(ClearVotingConfigExclusionsResponse response) {
|
||||||
onResponse.accept(response);
|
onResponse.accept(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,8 +205,8 @@ public class TransportClearVotingTombstonesActionTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClearVotingTombstonesResponse read(StreamInput in) throws IOException {
|
public ClearVotingConfigExclusionsResponse read(StreamInput in) throws IOException {
|
||||||
return new ClearVotingTombstonesResponse(in);
|
return new ClearVotingConfigExclusionsResponse(in);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -88,7 +88,7 @@ public class ClusterRerouteResponseTests extends ESTestCase {
|
||||||
" \"term\" : 0,\n" +
|
" \"term\" : 0,\n" +
|
||||||
" \"last_committed_config\" : [ ],\n" +
|
" \"last_committed_config\" : [ ],\n" +
|
||||||
" \"last_accepted_config\" : [ ],\n" +
|
" \"last_accepted_config\" : [ ],\n" +
|
||||||
" \"voting_tombstones\" : [ ]\n" +
|
" \"voting_config_exclusions\" : [ ]\n" +
|
||||||
" },\n" +
|
" },\n" +
|
||||||
" \"templates\" : { },\n" +
|
" \"templates\" : { },\n" +
|
||||||
" \"indices\" : {\n" +
|
" \"indices\" : {\n" +
|
||||||
|
@ -183,7 +183,7 @@ public class ClusterRerouteResponseTests extends ESTestCase {
|
||||||
" \"term\" : 0,\n" +
|
" \"term\" : 0,\n" +
|
||||||
" \"last_committed_config\" : [ ],\n" +
|
" \"last_committed_config\" : [ ],\n" +
|
||||||
" \"last_accepted_config\" : [ ],\n" +
|
" \"last_accepted_config\" : [ ],\n" +
|
||||||
" \"voting_tombstones\" : [ ]\n" +
|
" \"voting_config_exclusions\" : [ ]\n" +
|
||||||
" },\n" +
|
" },\n" +
|
||||||
" \"templates\" : { },\n" +
|
" \"templates\" : { },\n" +
|
||||||
" \"indices\" : {\n" +
|
" \"indices\" : {\n" +
|
||||||
|
|
|
@ -23,7 +23,7 @@ import com.carrotsearch.hppc.cursors.ObjectCursor;
|
||||||
import org.elasticsearch.cluster.block.ClusterBlock;
|
import org.elasticsearch.cluster.block.ClusterBlock;
|
||||||
import org.elasticsearch.cluster.block.ClusterBlocks;
|
import org.elasticsearch.cluster.block.ClusterBlocks;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||||
import org.elasticsearch.cluster.metadata.IndexGraveyard;
|
import org.elasticsearch.cluster.metadata.IndexGraveyard;
|
||||||
import org.elasticsearch.cluster.metadata.IndexGraveyardTests;
|
import org.elasticsearch.cluster.metadata.IndexGraveyardTests;
|
||||||
|
@ -208,7 +208,7 @@ public class ClusterStateDiffIT extends ESIntegTestCase {
|
||||||
new CoordinationMetaData.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false))));
|
new CoordinationMetaData.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false))));
|
||||||
}
|
}
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
metaBuilder.addVotingTombstone(new VotingTombstone(randomNode("node-" + randomAlphaOfLength(10))));
|
metaBuilder.addVotingConfigExclusion(new VotingConfigExclusion(randomNode("node-" + randomAlphaOfLength(10))));
|
||||||
}
|
}
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
package org.elasticsearch.cluster.coordination;
|
package org.elasticsearch.cluster.coordination;
|
||||||
|
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||||
import org.elasticsearch.common.util.set.Sets;
|
import org.elasticsearch.common.util.set.Sets;
|
||||||
|
@ -94,29 +94,29 @@ public class CoordinationMetaDataTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testVotingTombstoneSerializationEqualsHashCode() {
|
public void testVotingTombstoneSerializationEqualsHashCode() {
|
||||||
VotingTombstone tombstone = new VotingTombstone(randomAlphaOfLength(10), randomAlphaOfLength(10));
|
VotingConfigExclusion tombstone = new VotingConfigExclusion(randomAlphaOfLength(10), randomAlphaOfLength(10));
|
||||||
EqualsHashCodeTestUtils.checkEqualsAndHashCode(tombstone,
|
EqualsHashCodeTestUtils.checkEqualsAndHashCode(tombstone,
|
||||||
orig -> ESTestCase.copyWriteable(orig, new NamedWriteableRegistry(Collections.emptyList()), VotingTombstone::new),
|
orig -> ESTestCase.copyWriteable(orig, new NamedWriteableRegistry(Collections.emptyList()), VotingConfigExclusion::new),
|
||||||
orig -> randomlyChangeVotingTombstone(orig));
|
orig -> randomlyChangeVotingTombstone(orig));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testVotingTombstoneXContent() throws IOException {
|
public void testVotingTombstoneXContent() throws IOException {
|
||||||
VotingTombstone originalTombstone = new VotingTombstone(randomAlphaOfLength(10), randomAlphaOfLength(10));
|
VotingConfigExclusion originalTombstone = new VotingConfigExclusion(randomAlphaOfLength(10), randomAlphaOfLength(10));
|
||||||
|
|
||||||
final XContentBuilder builder = JsonXContent.contentBuilder();
|
final XContentBuilder builder = JsonXContent.contentBuilder();
|
||||||
originalTombstone.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
originalTombstone.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||||
|
|
||||||
try (XContentParser parser = createParser(JsonXContent.jsonXContent, BytesReference.bytes(builder))) {
|
try (XContentParser parser = createParser(JsonXContent.jsonXContent, BytesReference.bytes(builder))) {
|
||||||
final VotingTombstone fromXContentTombstone = VotingTombstone.fromXContent(parser);
|
final VotingConfigExclusion fromXContentTombstone = VotingConfigExclusion.fromXContent(parser);
|
||||||
assertThat(originalTombstone, equalTo(fromXContentTombstone));
|
assertThat(originalTombstone, equalTo(fromXContentTombstone));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private VotingTombstone randomlyChangeVotingTombstone(VotingTombstone tombstone) {
|
private VotingConfigExclusion randomlyChangeVotingTombstone(VotingConfigExclusion tombstone) {
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
return new VotingTombstone(randomAlphaOfLength(10), tombstone.getNodeName());
|
return new VotingConfigExclusion(randomAlphaOfLength(10), tombstone.getNodeName());
|
||||||
} else {
|
} else {
|
||||||
return new VotingTombstone(tombstone.getNodeId(), randomAlphaOfLength(10));
|
return new VotingConfigExclusion(tombstone.getNodeId(), randomAlphaOfLength(10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,11 +136,11 @@ public class CoordinationMetaDataTests extends ESTestCase {
|
||||||
return new VotingConfiguration(newNodeIds);
|
return new VotingConfiguration(newNodeIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<VotingTombstone> randomVotingTombstones() {
|
private Set<VotingConfigExclusion> randomVotingTombstones() {
|
||||||
final int size = randomIntBetween(1, 10);
|
final int size = randomIntBetween(1, 10);
|
||||||
final Set<VotingTombstone> nodes = new HashSet<>(size);
|
final Set<VotingConfigExclusion> nodes = new HashSet<>(size);
|
||||||
while (nodes.size() < size) {
|
while (nodes.size() < size) {
|
||||||
assertTrue(nodes.add(new VotingTombstone(randomAlphaOfLength(10), randomAlphaOfLength(10))));
|
assertTrue(nodes.add(new VotingConfigExclusion(randomAlphaOfLength(10), randomAlphaOfLength(10))));
|
||||||
}
|
}
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
@ -163,10 +163,10 @@ public class CoordinationMetaDataTests extends ESTestCase {
|
||||||
builder.lastAcceptedConfiguration(randomlyChangeVotingConfiguration(meta.getLastAcceptedConfiguration()));
|
builder.lastAcceptedConfiguration(randomlyChangeVotingConfiguration(meta.getLastAcceptedConfiguration()));
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (meta.getVotingTombstones().isEmpty() == false && randomBoolean()) {
|
if (meta.getVotingConfigExclusions().isEmpty() == false && randomBoolean()) {
|
||||||
builder.clearVotingTombstones();
|
builder.clearVotingConfigExclusions();
|
||||||
} else {
|
} else {
|
||||||
randomVotingTombstones().forEach(dn -> builder.addVotingTombstone(dn));
|
randomVotingTombstones().forEach(dn -> builder.addVotingConfigExclusion(dn));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
|
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
|
||||||
import org.elasticsearch.cluster.ClusterModule;
|
import org.elasticsearch.cluster.ClusterModule;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.UUIDs;
|
import org.elasticsearch.common.UUIDs;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
|
@ -415,18 +415,18 @@ public class MetaDataTests extends ESTestCase {
|
||||||
return new CoordinationMetaData.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(randomInt(10), 20, false)));
|
return new CoordinationMetaData.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(randomInt(10), 20, false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<VotingTombstone> randomVotingTombstones() {
|
private Set<VotingConfigExclusion> randomVotingConfigExclusions() {
|
||||||
final int size = randomIntBetween(0, 10);
|
final int size = randomIntBetween(0, 10);
|
||||||
final Set<VotingTombstone> nodes = new HashSet<>(size);
|
final Set<VotingConfigExclusion> nodes = new HashSet<>(size);
|
||||||
while (nodes.size() < size) {
|
while (nodes.size() < size) {
|
||||||
assertTrue(nodes.add(new VotingTombstone(randomAlphaOfLength(10), randomAlphaOfLength(10))));
|
assertTrue(nodes.add(new VotingConfigExclusion(randomAlphaOfLength(10), randomAlphaOfLength(10))));
|
||||||
}
|
}
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testXContentWithCoordinationMetaData() throws IOException {
|
public void testXContentWithCoordinationMetaData() throws IOException {
|
||||||
CoordinationMetaData originalMeta = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(), randomVotingConfig(),
|
CoordinationMetaData originalMeta = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(), randomVotingConfig(),
|
||||||
randomVotingTombstones());
|
randomVotingConfigExclusions());
|
||||||
|
|
||||||
MetaData metaData = MetaData.builder().coordinationMetaData(originalMeta).build();
|
MetaData metaData = MetaData.builder().coordinationMetaData(originalMeta).build();
|
||||||
|
|
||||||
|
@ -443,10 +443,10 @@ public class MetaDataTests extends ESTestCase {
|
||||||
|
|
||||||
public void testGlobalStateEqualsCoordinationMetaData() {
|
public void testGlobalStateEqualsCoordinationMetaData() {
|
||||||
CoordinationMetaData coordinationMetaData1 = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(),
|
CoordinationMetaData coordinationMetaData1 = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(),
|
||||||
randomVotingConfig(), randomVotingTombstones());
|
randomVotingConfig(), randomVotingConfigExclusions());
|
||||||
MetaData metaData1 = MetaData.builder().coordinationMetaData(coordinationMetaData1).build();
|
MetaData metaData1 = MetaData.builder().coordinationMetaData(coordinationMetaData1).build();
|
||||||
CoordinationMetaData coordinationMetaData2 = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(),
|
CoordinationMetaData coordinationMetaData2 = new CoordinationMetaData(randomNonNegativeLong(), randomVotingConfig(),
|
||||||
randomVotingConfig(), randomVotingTombstones());
|
randomVotingConfig(), randomVotingConfigExclusions());
|
||||||
MetaData metaData2 = MetaData.builder().coordinationMetaData(coordinationMetaData2).build();
|
MetaData metaData2 = MetaData.builder().coordinationMetaData(coordinationMetaData2).build();
|
||||||
|
|
||||||
assertTrue(MetaData.isGlobalStateEquals(metaData1, metaData1));
|
assertTrue(MetaData.isGlobalStateEquals(metaData1, metaData1));
|
||||||
|
|
|
@ -23,7 +23,7 @@ import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.cluster.ClusterName;
|
import org.elasticsearch.cluster.ClusterName;
|
||||||
import org.elasticsearch.cluster.ClusterState;
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData;
|
||||||
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingTombstone;
|
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfigExclusion;
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||||
import org.elasticsearch.cluster.metadata.Manifest;
|
import org.elasticsearch.cluster.metadata.Manifest;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
|
@ -145,7 +145,7 @@ public class GatewayMetaStatePersistedStateTests extends ESTestCase {
|
||||||
new CoordinationMetaData.VotingConfiguration(
|
new CoordinationMetaData.VotingConfiguration(
|
||||||
Sets.newHashSet(generateRandomStringArray(10, 10, false))));
|
Sets.newHashSet(generateRandomStringArray(10, 10, false))));
|
||||||
for (int i = 0; i < randomIntBetween(0, 5); i++) {
|
for (int i = 0; i < randomIntBetween(0, 5); i++) {
|
||||||
builder.addVotingTombstone(new VotingTombstone(randomAlphaOfLength(10), randomAlphaOfLength(10)));
|
builder.addVotingConfigExclusion(new VotingConfigExclusion(randomAlphaOfLength(10), randomAlphaOfLength(10)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -31,10 +31,10 @@ import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.lucene.store.AlreadyClosedException;
|
import org.apache.lucene.store.AlreadyClosedException;
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.AddVotingTombstonesAction;
|
import org.elasticsearch.action.admin.cluster.configuration.AddVotingConfigExclusionsAction;
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.AddVotingTombstonesRequest;
|
import org.elasticsearch.action.admin.cluster.configuration.AddVotingConfigExclusionsRequest;
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingTombstonesAction;
|
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingConfigExclusionsRequest;
|
||||||
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingTombstonesRequest;
|
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingConfigExclusionsAction;
|
||||||
import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
|
import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
|
||||||
import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags;
|
import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags;
|
||||||
import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags.Flag;
|
import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags.Flag;
|
||||||
|
@ -1636,7 +1636,7 @@ public final class InternalTestCluster extends TestCluster {
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void stopNodesAndClients(Collection<NodeAndClient> nodeAndClients) throws IOException {
|
private synchronized void stopNodesAndClients(Collection<NodeAndClient> nodeAndClients) throws IOException {
|
||||||
final Set<String> withdrawnNodeIds = new HashSet<>();
|
final Set<String> excludedNodeIds = new HashSet<>();
|
||||||
|
|
||||||
if (autoManageMinMasterNodes && nodeAndClients.size() > 0) {
|
if (autoManageMinMasterNodes && nodeAndClients.size() > 0) {
|
||||||
|
|
||||||
|
@ -1649,13 +1649,13 @@ public final class InternalTestCluster extends TestCluster {
|
||||||
// However, we do not yet have a way to be sure there's a majority left, because the voting configuration may not yet have
|
// However, we do not yet have a way to be sure there's a majority left, because the voting configuration may not yet have
|
||||||
// been updated when the previous nodes shut down, so we must always explicitly withdraw votes.
|
// been updated when the previous nodes shut down, so we must always explicitly withdraw votes.
|
||||||
// TODO add cluster health API to check that voting configuration is optimal so this isn't always needed
|
// TODO add cluster health API to check that voting configuration is optimal so this isn't always needed
|
||||||
nodeAndClients.stream().filter(NodeAndClient::isMasterEligible).map(NodeAndClient::getName).forEach(withdrawnNodeIds::add);
|
nodeAndClients.stream().filter(NodeAndClient::isMasterEligible).map(NodeAndClient::getName).forEach(excludedNodeIds::add);
|
||||||
assert withdrawnNodeIds.size() == stoppingMasters;
|
assert excludedNodeIds.size() == stoppingMasters;
|
||||||
|
|
||||||
logger.info("withdrawing votes from {} prior to shutdown", withdrawnNodeIds);
|
logger.info("adding voting config exclusions {} prior to shutdown", excludedNodeIds);
|
||||||
try {
|
try {
|
||||||
client().execute(AddVotingTombstonesAction.INSTANCE,
|
client().execute(AddVotingConfigExclusionsAction.INSTANCE,
|
||||||
new AddVotingTombstonesRequest(withdrawnNodeIds.toArray(new String[0]))).get();
|
new AddVotingConfigExclusionsRequest(excludedNodeIds.toArray(new String[0]))).get();
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
throw new AssertionError("unexpected", e);
|
throw new AssertionError("unexpected", e);
|
||||||
}
|
}
|
||||||
|
@ -1673,10 +1673,10 @@ public final class InternalTestCluster extends TestCluster {
|
||||||
nodeAndClient.close();
|
nodeAndClient.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (withdrawnNodeIds.isEmpty() == false) {
|
if (excludedNodeIds.isEmpty() == false) {
|
||||||
logger.info("removing voting tombstones for {} after shutdown", withdrawnNodeIds);
|
logger.info("removing voting config exclusions for {} after shutdown", excludedNodeIds);
|
||||||
try {
|
try {
|
||||||
client().execute(ClearVotingTombstonesAction.INSTANCE, new ClearVotingTombstonesRequest()).get();
|
client().execute(ClearVotingConfigExclusionsAction.INSTANCE, new ClearVotingConfigExclusionsRequest()).get();
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
throw new AssertionError("unexpected", e);
|
throw new AssertionError("unexpected", e);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue