Move parsing of allocation commands into REST
Port them to the ObjectParser. Don't let plugins register custom allocation commands
This commit is contained in:
parent
f210605af8
commit
a93f578bf6
|
@ -37,8 +37,6 @@
|
|||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]admin[/\\]cluster[/\\]repositories[/\\]put[/\\]TransportPutRepositoryAction.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]admin[/\\]cluster[/\\]repositories[/\\]verify[/\\]TransportVerifyRepositoryAction.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]admin[/\\]cluster[/\\]repositories[/\\]verify[/\\]VerifyRepositoryRequestBuilder.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]admin[/\\]cluster[/\\]reroute[/\\]ClusterRerouteRequest.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]admin[/\\]cluster[/\\]reroute[/\\]ClusterRerouteRequestBuilder.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]admin[/\\]cluster[/\\]reroute[/\\]TransportClusterRerouteAction.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]admin[/\\]cluster[/\\]settings[/\\]ClusterUpdateSettingsAction.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]admin[/\\]cluster[/\\]settings[/\\]ClusterUpdateSettingsRequestBuilder.java" checks="LineLength" />
|
||||
|
|
|
@ -19,20 +19,15 @@
|
|||
|
||||
package org.elasticsearch.action.admin.cluster.reroute;
|
||||
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.support.master.AcknowledgedRequest;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommandRegistry;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommands;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Request to submit cluster reroute allocation commands
|
||||
|
@ -109,8 +104,8 @@ public class ClusterRerouteRequest extends AcknowledgedRequest<ClusterRerouteReq
|
|||
/**
|
||||
* Set the allocation commands to execute.
|
||||
*/
|
||||
public ClusterRerouteRequest commands(AllocationCommand... commands) {
|
||||
this.commands = new AllocationCommands(commands);
|
||||
public ClusterRerouteRequest commands(AllocationCommands commands) {
|
||||
this.commands = commands;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -121,35 +116,6 @@ public class ClusterRerouteRequest extends AcknowledgedRequest<ClusterRerouteReq
|
|||
return commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source for the request.
|
||||
*/
|
||||
public ClusterRerouteRequest source(BytesReference source, AllocationCommandRegistry registry, ParseFieldMatcher parseFieldMatcher)
|
||||
throws Exception {
|
||||
try (XContentParser parser = XContentHelper.createParser(source)) {
|
||||
XContentParser.Token token;
|
||||
String currentFieldName = null;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
if ("commands".equals(currentFieldName)) {
|
||||
this.commands = AllocationCommands.fromXContent(parser, parseFieldMatcher, registry);
|
||||
} else {
|
||||
throw new ElasticsearchParseException("failed to parse reroute request, got start array with wrong field name [{}]", currentFieldName);
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if ("dry_run".equals(currentFieldName) || "dryRun".equals(currentFieldName)) {
|
||||
dryRun = parser.booleanValue();
|
||||
} else {
|
||||
throw new ElasticsearchParseException("failed to parse reroute request, got value with wrong field name [{}]", currentFieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionRequestValidationException validate() {
|
||||
return null;
|
||||
|
@ -174,4 +140,25 @@ public class ClusterRerouteRequest extends AcknowledgedRequest<ClusterRerouteReq
|
|||
out.writeBoolean(retryFailed);
|
||||
writeTimeout(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
ClusterRerouteRequest other = (ClusterRerouteRequest) obj;
|
||||
// Override equals and hashCode for testing
|
||||
return Objects.equals(commands, other.commands) &&
|
||||
Objects.equals(dryRun, other.dryRun) &&
|
||||
Objects.equals(explain, other.explain) &&
|
||||
Objects.equals(timeout, other.timeout) &&
|
||||
Objects.equals(retryFailed, other.retryFailed) &&
|
||||
Objects.equals(masterNodeTimeout, other.masterNodeTimeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Override equals and hashCode for testing
|
||||
return Objects.hash(commands, dryRun, explain, timeout, retryFailed, masterNodeTimeout);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,13 +22,12 @@ package org.elasticsearch.action.admin.cluster.reroute;
|
|||
import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
|
||||
/**
|
||||
* Builder for a cluster reroute request
|
||||
*/
|
||||
public class ClusterRerouteRequestBuilder extends AcknowledgedRequestBuilder<ClusterRerouteRequest, ClusterRerouteResponse, ClusterRerouteRequestBuilder> {
|
||||
|
||||
public class ClusterRerouteRequestBuilder
|
||||
extends AcknowledgedRequestBuilder<ClusterRerouteRequest, ClusterRerouteResponse, ClusterRerouteRequestBuilder> {
|
||||
public ClusterRerouteRequestBuilder(ElasticsearchClient client, ClusterRerouteAction action) {
|
||||
super(client, action, new ClusterRerouteRequest());
|
||||
}
|
||||
|
@ -68,12 +67,4 @@ public class ClusterRerouteRequestBuilder extends AcknowledgedRequestBuilder<Clu
|
|||
request.setRetryFailed(retryFailed);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the commands for the request to execute.
|
||||
*/
|
||||
public ClusterRerouteRequestBuilder setCommands(AllocationCommand... commands) throws Exception {
|
||||
request.commands(commands);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -38,6 +38,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -228,4 +229,22 @@ public abstract class AbstractAllocateAllocationCommand implements AllocationCom
|
|||
|
||||
protected void extraXContent(XContentBuilder builder) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
AbstractAllocateAllocationCommand other = (AbstractAllocateAllocationCommand) obj;
|
||||
// Override equals and hashCode for testing
|
||||
return Objects.equals(index, other.index) &&
|
||||
Objects.equals(shardId, other.shardId) &&
|
||||
Objects.equals(node, other.node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Override equals and hashCode for testing
|
||||
return Objects.hash(index, shardId, node);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,6 +136,4 @@ public class AllocateReplicaAllocationCommand extends AbstractAllocateAllocation
|
|||
initializeUnassignedShard(allocation, routingNodes, routingNode, shardRouting);
|
||||
return new RerouteExplanation(this, decision);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -22,13 +22,16 @@ package org.elasticsearch.cluster.routing.allocation.command;
|
|||
import org.elasticsearch.cluster.routing.allocation.RerouteExplanation;
|
||||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteable;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This interface defines the basic methods of commands for allocation
|
||||
* A command to move shards in some way.
|
||||
*
|
||||
* Commands are registered in {@link NetworkModule}.
|
||||
*/
|
||||
public interface AllocationCommand extends NamedWriteable, ToXContent {
|
||||
interface Parser<T extends AllocationCommand> {
|
||||
|
|
|
@ -20,12 +20,12 @@
|
|||
package org.elasticsearch.cluster.routing.allocation.command;
|
||||
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.action.support.ToXContentToBytes;
|
||||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
|
||||
import org.elasticsearch.cluster.routing.allocation.RoutingExplanations;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
|
@ -33,12 +33,13 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A simple {@link AllocationCommand} composite managing several
|
||||
* {@link AllocationCommand} implementations
|
||||
*/
|
||||
public class AllocationCommands {
|
||||
public class AllocationCommands extends ToXContentToBytes {
|
||||
private final List<AllocationCommand> commands = new ArrayList<>();
|
||||
|
||||
/**
|
||||
|
@ -171,21 +172,31 @@ public class AllocationCommands {
|
|||
return commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes {@link AllocationCommands} to a {@link XContentBuilder}
|
||||
*
|
||||
* @param commands {@link AllocationCommands} to write
|
||||
* @param builder {@link XContentBuilder} to use
|
||||
* @param params Parameters to use for building
|
||||
* @throws IOException if something bad happens while building the content
|
||||
*/
|
||||
public static void toXContent(AllocationCommands commands, XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startArray("commands");
|
||||
for (AllocationCommand command : commands.commands) {
|
||||
for (AllocationCommand command : commands) {
|
||||
builder.startObject();
|
||||
builder.field(command.name(), command);
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endArray();
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
AllocationCommands other = (AllocationCommands) obj;
|
||||
// Override equals and hashCode for testing
|
||||
return Objects.equals(commands, other.commands);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Override equals and hashCode for testing
|
||||
return Objects.hashCode(commands);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,4 +83,18 @@ public abstract class BasePrimaryAllocationCommand extends AbstractAllocateAlloc
|
|||
protected void extraXContent(XContentBuilder builder) throws IOException {
|
||||
builder.field(ACCEPT_DATA_LOSS_FIELD, acceptDataLoss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (false == super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
BasePrimaryAllocationCommand other = (BasePrimaryAllocationCommand) obj;
|
||||
return acceptDataLoss == other.acceptDataLoss;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * super.hashCode() + Boolean.hashCode(acceptDataLoss);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.elasticsearch.cluster.routing.ShardRoutingState.RELOCATING;
|
||||
|
||||
|
@ -240,4 +241,23 @@ public class CancelAllocationCommand implements AllocationCommand {
|
|||
}
|
||||
return new CancelAllocationCommand(index, shardId, nodeId, allowPrimary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
CancelAllocationCommand other = (CancelAllocationCommand) obj;
|
||||
// Override equals and hashCode for testing
|
||||
return Objects.equals(index, other.index) &&
|
||||
Objects.equals(shardId, other.shardId) &&
|
||||
Objects.equals(node, other.node) &&
|
||||
Objects.equals(allowPrimary, other.allowPrimary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Override equals and hashCode for testing
|
||||
return Objects.hash(index, shardId, node, allowPrimary);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A command that moves a shard from a specific node to another node.<br>
|
||||
|
@ -195,4 +196,23 @@ public class MoveAllocationCommand implements AllocationCommand {
|
|||
}
|
||||
return new MoveAllocationCommand(index, shardId, fromNode, toNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
MoveAllocationCommand other = (MoveAllocationCommand) obj;
|
||||
// Override equals and hashCode for testing
|
||||
return Objects.equals(index, other.index) &&
|
||||
Objects.equals(shardId, other.shardId) &&
|
||||
Objects.equals(fromNode, other.fromNode) &&
|
||||
Objects.equals(toNode, other.toNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Override equals and hashCode for testing
|
||||
return Objects.hash(index, shardId, fromNode, toNode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,6 @@
|
|||
|
||||
package org.elasticsearch.common.network;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.action.support.replication.ReplicationTask;
|
||||
import org.elasticsearch.client.transport.TransportClientNodesService;
|
||||
import org.elasticsearch.client.transport.support.TransportProxyClient;
|
||||
|
@ -68,6 +65,12 @@ import org.elasticsearch.rest.action.admin.cluster.snapshots.restore.RestRestore
|
|||
import org.elasticsearch.rest.action.admin.cluster.snapshots.status.RestSnapshotsStatusAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.state.RestClusterStateAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.stats.RestClusterStatsAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestDeleteSearchTemplateAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestDeleteStoredScriptAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestGetSearchTemplateAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestGetStoredScriptAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestPutSearchTemplateAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestPutStoredScriptAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.tasks.RestPendingClusterTasksAction;
|
||||
import org.elasticsearch.rest.action.admin.indices.alias.RestIndicesAliasesAction;
|
||||
import org.elasticsearch.rest.action.admin.indices.alias.delete.RestIndexDeleteAliasesAction;
|
||||
|
@ -134,17 +137,11 @@ import org.elasticsearch.rest.action.ingest.RestGetPipelineAction;
|
|||
import org.elasticsearch.rest.action.ingest.RestPutPipelineAction;
|
||||
import org.elasticsearch.rest.action.ingest.RestSimulatePipelineAction;
|
||||
import org.elasticsearch.rest.action.main.RestMainAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestDeleteStoredScriptAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestGetStoredScriptAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestPutStoredScriptAction;
|
||||
import org.elasticsearch.rest.action.search.RestClearScrollAction;
|
||||
import org.elasticsearch.rest.action.search.RestMultiSearchAction;
|
||||
import org.elasticsearch.rest.action.search.RestSearchAction;
|
||||
import org.elasticsearch.rest.action.search.RestSearchScrollAction;
|
||||
import org.elasticsearch.rest.action.suggest.RestSuggestAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestDeleteSearchTemplateAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestGetSearchTemplateAction;
|
||||
import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestPutSearchTemplateAction;
|
||||
import org.elasticsearch.rest.action.termvectors.RestMultiTermVectorsAction;
|
||||
import org.elasticsearch.rest.action.termvectors.RestTermVectorsAction;
|
||||
import org.elasticsearch.rest.action.update.RestUpdateAction;
|
||||
|
@ -154,6 +151,9 @@ import org.elasticsearch.transport.TransportService;
|
|||
import org.elasticsearch.transport.local.LocalTransport;
|
||||
import org.elasticsearch.transport.netty.NettyTransport;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A module to handle registering and binding all network related classes.
|
||||
*/
|
||||
|
@ -397,7 +397,7 @@ public class NetworkModule extends AbstractModule {
|
|||
* @param commandName the names under which the command should be parsed. The {@link ParseField#getPreferredName()} is special because
|
||||
* it is the name under which the command's reader is registered.
|
||||
*/
|
||||
public <T extends AllocationCommand> void registerAllocationCommand(Writeable.Reader<T> reader, AllocationCommand.Parser<T> parser,
|
||||
private <T extends AllocationCommand> void registerAllocationCommand(Writeable.Reader<T> reader, AllocationCommand.Parser<T> parser,
|
||||
ParseField commandName) {
|
||||
allocationCommandRegistry.register(parser, commandName);
|
||||
namedWriteableRegistry.register(AllocationCommand.class, commandName.getPreferredName(), reader);
|
||||
|
|
|
@ -25,12 +25,20 @@ import org.elasticsearch.client.Client;
|
|||
import org.elasticsearch.client.Requests;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommandRegistry;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommands;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.ParseFieldMatcherSupplier;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsFilter;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
|
@ -43,12 +51,17 @@ import java.util.EnumSet;
|
|||
/**
|
||||
*/
|
||||
public class RestClusterRerouteAction extends BaseRestHandler {
|
||||
private static final ObjectParser<ClusterRerouteRequest, ParseContext> PARSER = new ObjectParser<>("cluster_reroute");
|
||||
static {
|
||||
PARSER.declareField((p, v, c) -> v.commands(AllocationCommands.fromXContent(p, c.getParseFieldMatcher(), c.registry)),
|
||||
new ParseField("commands"), ValueType.OBJECT_ARRAY);
|
||||
PARSER.declareBoolean(ClusterRerouteRequest::dryRun, new ParseField("dry_run"));
|
||||
}
|
||||
|
||||
private final SettingsFilter settingsFilter;
|
||||
|
||||
private static String DEFAULT_METRICS = Strings
|
||||
private static final String DEFAULT_METRICS = Strings
|
||||
.arrayToCommaDelimitedString(EnumSet.complementOf(EnumSet.of(ClusterState.Metric.METADATA)).toArray());
|
||||
|
||||
private final SettingsFilter settingsFilter;
|
||||
private final AllocationCommandRegistry registry;
|
||||
|
||||
@Inject
|
||||
|
@ -62,16 +75,7 @@ public class RestClusterRerouteAction extends BaseRestHandler {
|
|||
|
||||
@Override
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) throws Exception {
|
||||
final ClusterRerouteRequest clusterRerouteRequest = Requests.clusterRerouteRequest();
|
||||
clusterRerouteRequest.dryRun(request.paramAsBoolean("dry_run", clusterRerouteRequest.dryRun()));
|
||||
clusterRerouteRequest.setRetryFailed(request.paramAsBoolean("retry_failed", clusterRerouteRequest.isRetryFailed()));
|
||||
clusterRerouteRequest.explain(request.paramAsBoolean("explain", clusterRerouteRequest.explain()));
|
||||
clusterRerouteRequest.timeout(request.paramAsTime("timeout", clusterRerouteRequest.timeout()));
|
||||
clusterRerouteRequest.masterNodeTimeout(request.paramAsTime("master_timeout", clusterRerouteRequest.masterNodeTimeout()));
|
||||
if (request.hasContent()) {
|
||||
clusterRerouteRequest.source(request.content(), registry, parseFieldMatcher);
|
||||
}
|
||||
|
||||
ClusterRerouteRequest clusterRerouteRequest = createRequest(request, registry, parseFieldMatcher);
|
||||
client.admin().cluster().reroute(clusterRerouteRequest, new AcknowledgedRestListener<ClusterRerouteResponse>(channel) {
|
||||
@Override
|
||||
protected void addCustomFields(XContentBuilder builder, ClusterRerouteResponse response) throws IOException {
|
||||
|
@ -90,4 +94,35 @@ public class RestClusterRerouteAction extends BaseRestHandler {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static ClusterRerouteRequest createRequest(RestRequest request, AllocationCommandRegistry registry,
|
||||
ParseFieldMatcher parseFieldMatcher) throws IOException {
|
||||
ClusterRerouteRequest clusterRerouteRequest = Requests.clusterRerouteRequest();
|
||||
clusterRerouteRequest.dryRun(request.paramAsBoolean("dry_run", clusterRerouteRequest.dryRun()));
|
||||
clusterRerouteRequest.explain(request.paramAsBoolean("explain", clusterRerouteRequest.explain()));
|
||||
clusterRerouteRequest.timeout(request.paramAsTime("timeout", clusterRerouteRequest.timeout()));
|
||||
clusterRerouteRequest.setRetryFailed(request.paramAsBoolean("retry_failed", clusterRerouteRequest.isRetryFailed()));
|
||||
clusterRerouteRequest.masterNodeTimeout(request.paramAsTime("master_timeout", clusterRerouteRequest.masterNodeTimeout()));
|
||||
if (request.hasContent()) {
|
||||
try (XContentParser parser = XContentHelper.createParser(request.content())) {
|
||||
PARSER.parse(parser, clusterRerouteRequest, new ParseContext(registry, parseFieldMatcher));
|
||||
}
|
||||
}
|
||||
return clusterRerouteRequest;
|
||||
}
|
||||
|
||||
private static class ParseContext implements ParseFieldMatcherSupplier {
|
||||
private final AllocationCommandRegistry registry;
|
||||
private final ParseFieldMatcher parseFieldMatcher;
|
||||
|
||||
private ParseContext(AllocationCommandRegistry registry, ParseFieldMatcher parseFieldMatcher) {
|
||||
this.registry = registry;
|
||||
this.parseFieldMatcher = parseFieldMatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParseFieldMatcher getParseFieldMatcher() {
|
||||
return parseFieldMatcher;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action.admin.cluster.reroute;
|
||||
|
||||
import org.elasticsearch.action.support.master.AcknowledgedRequest;
|
||||
import org.elasticsearch.action.support.master.MasterNodeRequest;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocateEmptyPrimaryAllocationCommand;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocateReplicaAllocationCommand;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocateStalePrimaryAllocationCommand;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommandRegistry;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.CancelAllocationCommand;
|
||||
import org.elasticsearch.cluster.routing.allocation.command.MoveAllocationCommand;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.action.admin.cluster.reroute.RestClusterRerouteAction;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.rest.FakeRestRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static org.elasticsearch.common.unit.TimeValue.timeValueMillis;
|
||||
|
||||
/**
|
||||
* Test for serialization and parsing of {@link ClusterRerouteRequest} and its commands. See the superclass for, well, everything.
|
||||
*/
|
||||
public class ClusterRerouteRequestTests extends ESTestCase {
|
||||
private static final int ROUNDS = 30;
|
||||
private final List<Supplier<AllocationCommand>> RANDOM_COMMAND_GENERATORS = unmodifiableList(Arrays.asList(
|
||||
() -> new AllocateReplicaAllocationCommand(randomAsciiOfLengthBetween(2, 10), between(0, 1000),
|
||||
randomAsciiOfLengthBetween(2, 10)),
|
||||
() -> new AllocateEmptyPrimaryAllocationCommand(randomAsciiOfLengthBetween(2, 10), between(0, 1000),
|
||||
randomAsciiOfLengthBetween(2, 10), randomBoolean()),
|
||||
() -> new AllocateStalePrimaryAllocationCommand(randomAsciiOfLengthBetween(2, 10), between(0, 1000),
|
||||
randomAsciiOfLengthBetween(2, 10), randomBoolean()),
|
||||
() -> new CancelAllocationCommand(randomAsciiOfLengthBetween(2, 10), between(0, 1000),
|
||||
randomAsciiOfLengthBetween(2, 10), randomBoolean()),
|
||||
() -> new MoveAllocationCommand(randomAsciiOfLengthBetween(2, 10), between(0, 1000),
|
||||
randomAsciiOfLengthBetween(2, 10), randomAsciiOfLengthBetween(2, 10))));
|
||||
private final NamedWriteableRegistry namedWriteableRegistry;
|
||||
private final AllocationCommandRegistry allocationCommandRegistry;
|
||||
|
||||
public ClusterRerouteRequestTests() {
|
||||
namedWriteableRegistry = new NamedWriteableRegistry();
|
||||
allocationCommandRegistry = new NetworkModule(null, null, true, namedWriteableRegistry).getAllocationCommandRegistry();
|
||||
}
|
||||
|
||||
private ClusterRerouteRequest randomRequest() {
|
||||
ClusterRerouteRequest request = new ClusterRerouteRequest();
|
||||
int commands = between(0, 10);
|
||||
for (int i = 0; i < commands; i++) {
|
||||
request.add(randomFrom(RANDOM_COMMAND_GENERATORS).get());
|
||||
}
|
||||
request.dryRun(randomBoolean());
|
||||
request.explain(randomBoolean());
|
||||
request.setRetryFailed(randomBoolean());
|
||||
return request;
|
||||
}
|
||||
|
||||
public void testEqualsAndHashCode() {
|
||||
for (int round = 0; round < ROUNDS; round++) {
|
||||
ClusterRerouteRequest request = randomRequest();
|
||||
assertEquals(request, request);
|
||||
assertEquals(request.hashCode(), request.hashCode());
|
||||
|
||||
ClusterRerouteRequest copy = new ClusterRerouteRequest()
|
||||
.add(request.getCommands().commands().toArray(new AllocationCommand[0]));
|
||||
copy.dryRun(request.dryRun()).explain(request.explain()).timeout(request.timeout()).setRetryFailed(request.isRetryFailed());
|
||||
copy.masterNodeTimeout(request.masterNodeTimeout());
|
||||
assertEquals(request, copy);
|
||||
assertEquals(copy, request); // Commutative
|
||||
assertEquals(request.hashCode(), copy.hashCode());
|
||||
|
||||
// Changing dryRun makes requests not equal
|
||||
copy.dryRun(!copy.dryRun());
|
||||
assertNotEquals(request, copy);
|
||||
assertNotEquals(request.hashCode(), copy.hashCode());
|
||||
copy.dryRun(!copy.dryRun());
|
||||
assertEquals(request, copy);
|
||||
assertEquals(request.hashCode(), copy.hashCode());
|
||||
|
||||
// Changing explain makes requests not equal
|
||||
copy.explain(!copy.explain());
|
||||
assertNotEquals(request, copy);
|
||||
assertNotEquals(request.hashCode(), copy.hashCode());
|
||||
copy.explain(!copy.explain());
|
||||
assertEquals(request, copy);
|
||||
assertEquals(request.hashCode(), copy.hashCode());
|
||||
|
||||
// Changing timeout makes requests not equal
|
||||
copy.timeout(timeValueMillis(request.timeout().millis() + 1));
|
||||
assertNotEquals(request, copy);
|
||||
assertNotEquals(request.hashCode(), copy.hashCode());
|
||||
copy.timeout(request.timeout());
|
||||
assertEquals(request, copy);
|
||||
assertEquals(request.hashCode(), copy.hashCode());
|
||||
|
||||
// Changing masterNodeTime makes requests not equal
|
||||
copy.masterNodeTimeout(timeValueMillis(request.masterNodeTimeout().millis() + 1));
|
||||
assertNotEquals(request, copy);
|
||||
assertNotEquals(request.hashCode(), copy.hashCode());
|
||||
copy.masterNodeTimeout(request.masterNodeTimeout());
|
||||
assertEquals(request, copy);
|
||||
assertEquals(request.hashCode(), copy.hashCode());
|
||||
|
||||
// Changing commands makes requests not equal
|
||||
copy.add(randomFrom(RANDOM_COMMAND_GENERATORS).get());
|
||||
assertNotEquals(request, copy);
|
||||
// Can't check hashCode because we can't be sure that changing commands changes the hashCode. It usually does but might not.
|
||||
}
|
||||
}
|
||||
|
||||
public void testSerialization() throws IOException {
|
||||
for (int round = 0; round < ROUNDS; round++) {
|
||||
ClusterRerouteRequest request = randomRequest();
|
||||
ClusterRerouteRequest copy = roundTripThroughBytes(request);
|
||||
assertEquals(request, copy);
|
||||
assertEquals(request.hashCode(), copy.hashCode());
|
||||
assertNotSame(request, copy);
|
||||
}
|
||||
}
|
||||
|
||||
public void testParsing() throws IOException {
|
||||
for (int round = 0; round < ROUNDS; round++) {
|
||||
ClusterRerouteRequest request = randomRequest();
|
||||
ClusterRerouteRequest copy = roundTripThroughRestRequest(request);
|
||||
assertEquals(request, copy);
|
||||
assertEquals(request.hashCode(), copy.hashCode());
|
||||
assertNotSame(request, copy);
|
||||
}
|
||||
}
|
||||
|
||||
private ClusterRerouteRequest roundTripThroughBytes(ClusterRerouteRequest original) throws IOException {
|
||||
try (BytesStreamOutput output = new BytesStreamOutput()) {
|
||||
original.writeTo(output);
|
||||
try (StreamInput in = new NamedWriteableAwareStreamInput(StreamInput.wrap(output.bytes()), namedWriteableRegistry)) {
|
||||
ClusterRerouteRequest copy = new ClusterRerouteRequest();
|
||||
copy.readFrom(in);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClusterRerouteRequest roundTripThroughRestRequest(ClusterRerouteRequest original) throws IOException {
|
||||
RestRequest restRequest = toRestRequest(original);
|
||||
return RestClusterRerouteAction.createRequest(restRequest, allocationCommandRegistry, ParseFieldMatcher.STRICT);
|
||||
}
|
||||
|
||||
private static RestRequest toRestRequest(ClusterRerouteRequest original) throws IOException {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
|
||||
boolean hasBody = false;
|
||||
if (randomBoolean()) {
|
||||
builder.prettyPrint();
|
||||
}
|
||||
builder.startObject();
|
||||
if (randomBoolean()) {
|
||||
params.put("dry_run", Boolean.toString(original.dryRun()));
|
||||
} else {
|
||||
hasBody = true;
|
||||
builder.field("dry_run", original.dryRun());
|
||||
}
|
||||
params.put("explain", Boolean.toString(original.explain()));
|
||||
if (false == original.timeout().equals(AcknowledgedRequest.DEFAULT_ACK_TIMEOUT) || randomBoolean()) {
|
||||
params.put("timeout", original.timeout().toString());
|
||||
}
|
||||
if (original.isRetryFailed() || randomBoolean()) {
|
||||
params.put("retry_failed", Boolean.toString(original.isRetryFailed()));
|
||||
}
|
||||
if (false == original.masterNodeTimeout().equals(MasterNodeRequest.DEFAULT_MASTER_NODE_TIMEOUT) || randomBoolean()) {
|
||||
params.put("master_timeout", original.masterNodeTimeout().toString());
|
||||
}
|
||||
if (original.getCommands() != null) {
|
||||
hasBody = true;
|
||||
original.getCommands().toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
}
|
||||
builder.endObject();
|
||||
|
||||
return new FakeRestRequest(emptyMap(), params, hasBody ? builder.bytes() : null);
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ public class ClusterRerouteTests extends ESAllocationTestCase {
|
|||
req.setRetryFailed(randomBoolean());
|
||||
req.dryRun(randomBoolean());
|
||||
req.explain(randomBoolean());
|
||||
req.commands(new AllocateEmptyPrimaryAllocationCommand("foo", 1, "bar", randomBoolean()));
|
||||
req.add(new AllocateEmptyPrimaryAllocationCommand("foo", 1, "bar", randomBoolean()));
|
||||
req.timeout(TimeValue.timeValueMillis(randomIntBetween(0, 100)));
|
||||
BytesStreamOutput out = new BytesStreamOutput();
|
||||
req.writeTo(out);
|
||||
|
|
|
@ -39,6 +39,11 @@ command corresponds to the old `allocate` command with `allow_primary` set to
|
|||
false. The new `allocate_empty_primary` command corresponds to the old
|
||||
`allocate` command with `allow_primary` set to true.
|
||||
|
||||
==== Custom Reroute Commands
|
||||
|
||||
Elasticsearch no longer supports plugins registering custom allocation
|
||||
commands. It was unused and hopefully unneeded.
|
||||
|
||||
==== `index.shared_filesystem.recover_on_any_node` changes
|
||||
|
||||
The behavior of `index.shared_filesystem.recover_on_any_node: true` has been
|
||||
|
|
Loading…
Reference in New Issue