-
Notifications
You must be signed in to change notification settings - Fork 2.3k
[Experimental] Start without joining a cluster if a "clusterless" ClusterPlugin is loaded #18479
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
d475498
[Experimental] Add a feature flag to start without joining a cluster
msfroh 41f9ada
Add changelog entry
msfroh fa30da5
Add back mistakenly removed imports
msfroh 21143b7
Fix IndicesClusterStateServiceRandomUpdatesTests
msfroh fb9f22f
Replace a couple of flag checks with field null-checks
msfroh 577c389
Extend ClusterService and ShardStateAction
msfroh 2c12580
Add Javadoc
msfroh d0c678a
Cannot bind a class to itself
msfroh e2ac28e
Delegate to public AbstractLifecycleComponent methods
msfroh 98583a4
Implement dummy Discovery and ClusterManagerService
msfroh a8f30db
Clean up a bit
msfroh 48413ae
Add explicit cast back to ClusterModule
msfroh 3dfcc04
Incorporate feedback from @rajiv-kv
msfroh fe6d0bc
Fix ClusterModuleTests
msfroh b9abeda
Remove feature flag
msfroh 1cbb72b
Update changelog
msfroh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
server/src/main/java/org/opensearch/cluster/action/shard/LocalShardStateAction.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| /* | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| * | ||
| * The OpenSearch Contributors require contributions made to | ||
| * this file be licensed under the Apache-2.0 license or a | ||
| * compatible open source license. | ||
| */ | ||
|
|
||
| package org.opensearch.cluster.action.shard; | ||
|
|
||
| import org.opensearch.cluster.ClusterState; | ||
| import org.opensearch.cluster.routing.IndexRoutingTable; | ||
| import org.opensearch.cluster.routing.IndexShardRoutingTable; | ||
| import org.opensearch.cluster.routing.RerouteService; | ||
| import org.opensearch.cluster.routing.RoutingTable; | ||
| import org.opensearch.cluster.routing.ShardRouting; | ||
| import org.opensearch.cluster.routing.allocation.AllocationService; | ||
| import org.opensearch.cluster.service.ClusterService; | ||
| import org.opensearch.common.inject.Inject; | ||
| import org.opensearch.core.action.ActionListener; | ||
| import org.opensearch.threadpool.ThreadPool; | ||
| import org.opensearch.transport.TransportService; | ||
|
|
||
| import java.util.function.Function; | ||
|
|
||
| /** | ||
| * A local implementation of {@link ShardStateAction} that applies shard state changes directly to the | ||
| * local cluster state. This is used in clusterless mode, where there is no cluster manager. | ||
| */ | ||
| public class LocalShardStateAction extends ShardStateAction { | ||
| @Inject | ||
| public LocalShardStateAction( | ||
| ClusterService clusterService, | ||
| TransportService transportService, | ||
| AllocationService allocationService, | ||
| RerouteService rerouteService, | ||
| ThreadPool threadPool | ||
| ) { | ||
| super(clusterService, transportService, allocationService, rerouteService, threadPool); | ||
| } | ||
|
|
||
| @Override | ||
| public void shardStarted( | ||
| ShardRouting shardRouting, | ||
| long primaryTerm, | ||
| String message, | ||
| ActionListener<Void> listener, | ||
| ClusterState currentState | ||
| ) { | ||
| Function<ClusterState, ClusterState> clusterStateUpdater = clusterState -> { | ||
| // We're running in clusterless mode. Apply the state change directly to the local cluster state. | ||
| RoutingTable routingTable = clusterState.getRoutingTable(); | ||
| IndexRoutingTable indexRoutingTable = routingTable.index(shardRouting.index()); | ||
|
|
||
| ClusterState.Builder clusterStateBuilder = ClusterState.builder(clusterState); | ||
| RoutingTable.Builder routingTableBuilder = RoutingTable.builder(routingTable); | ||
| IndexRoutingTable.Builder indexRoutingTableBuilder = IndexRoutingTable.builder(shardRouting.index()); | ||
| for (IndexShardRoutingTable indexShardRoutingTable : indexRoutingTable) { | ||
| if (indexShardRoutingTable.shardId().equals(shardRouting.shardId())) { | ||
| IndexShardRoutingTable.Builder indexShardRoutingTableBuilder = new IndexShardRoutingTable.Builder( | ||
| indexShardRoutingTable | ||
| ); | ||
| indexShardRoutingTableBuilder.removeShard(shardRouting); | ||
| indexShardRoutingTableBuilder.addShard(shardRouting.moveToStarted()); | ||
| indexRoutingTableBuilder.addIndexShard(indexShardRoutingTableBuilder.build()); | ||
| } else { | ||
| indexRoutingTableBuilder.addIndexShard(indexShardRoutingTable); | ||
| } | ||
| } | ||
| routingTableBuilder.add(indexRoutingTableBuilder); | ||
| clusterStateBuilder.routingTable(routingTableBuilder.build()); | ||
| return clusterStateBuilder.build(); | ||
| }; | ||
| clusterService.getClusterApplierService() | ||
| .updateClusterState("shard-started " + shardRouting.shardId(), clusterStateUpdater, (s, e) -> {}); | ||
| } | ||
|
|
||
| @Override | ||
| public void localShardFailed( | ||
| ShardRouting shardRouting, | ||
| String message, | ||
| Exception failure, | ||
| ActionListener<Void> listener, | ||
| ClusterState currentState | ||
| ) { | ||
| // Do not send a failure to the cluster manager, as we are running in clusterless mode. | ||
msfroh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
server/src/main/java/org/opensearch/cluster/service/LocalClusterService.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| /* | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| * | ||
| * The OpenSearch Contributors require contributions made to | ||
| * this file be licensed under the Apache-2.0 license or a | ||
| * compatible open source license. | ||
| */ | ||
|
|
||
| package org.opensearch.cluster.service; | ||
|
|
||
| import org.opensearch.cluster.ClusterManagerMetrics; | ||
| import org.opensearch.cluster.ClusterStateTaskConfig; | ||
| import org.opensearch.cluster.ClusterStateTaskExecutor; | ||
| import org.opensearch.cluster.ClusterStateTaskListener; | ||
| import org.opensearch.cluster.coordination.ClusterStatePublisher; | ||
| import org.opensearch.common.settings.ClusterSettings; | ||
| import org.opensearch.common.settings.Settings; | ||
| import org.opensearch.node.Node; | ||
| import org.opensearch.threadpool.ThreadPool; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * A local implementation of {@link ClusterService} that assumes we have no cluster manager. | ||
| * This is used in clusterless mode. | ||
| */ | ||
| public class LocalClusterService extends ClusterService { | ||
msfroh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| private static class DummyClusterManagerService extends ClusterManagerService { | ||
| private static final ClusterManagerThrottlingStats EMPTY_THROTTLING_STATS = new ClusterManagerThrottlingStats(); | ||
|
|
||
| public DummyClusterManagerService(Settings settings, ClusterSettings clusterSettings) { | ||
| super(settings, clusterSettings, null, null); | ||
| } | ||
|
|
||
| @Override | ||
| public synchronized void setClusterStatePublisher(ClusterStatePublisher publisher) {} | ||
|
|
||
| @Override | ||
| public ClusterManagerThrottlingStats getThrottlingStats() { | ||
| return EMPTY_THROTTLING_STATS; | ||
| } | ||
| } | ||
|
|
||
| public LocalClusterService( | ||
| Settings settings, | ||
| ClusterSettings clusterSettings, | ||
| ThreadPool threadPool, | ||
| ClusterManagerMetrics clusterManagerMetrics | ||
| ) { | ||
| super( | ||
| settings, | ||
| clusterSettings, | ||
| new DummyClusterManagerService(settings, clusterSettings), | ||
| new ClusterApplierService(Node.NODE_NAME_SETTING.get(settings), settings, clusterSettings, threadPool, clusterManagerMetrics) | ||
| ); | ||
| } | ||
|
|
||
| @Override | ||
| protected synchronized void doStart() { | ||
| getClusterApplierService().start(); | ||
| } | ||
|
|
||
| @Override | ||
| protected synchronized void doStop() { | ||
| getClusterApplierService().stop(); | ||
| } | ||
|
|
||
| @Override | ||
| protected synchronized void doClose() { | ||
| getClusterApplierService().close(); | ||
| } | ||
|
|
||
| @Override | ||
| public ClusterManagerTaskThrottler.ThrottlingKey registerClusterManagerTask(ClusterManagerTask task, boolean throttlingEnabled) { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public <T> void submitStateUpdateTasks( | ||
| final String source, | ||
| final Map<T, ClusterStateTaskListener> tasks, | ||
| final ClusterStateTaskConfig config, | ||
| final ClusterStateTaskExecutor<T> executor | ||
| ) { | ||
| throw new UnsupportedOperationException("Cannot submit cluster state update tasks when cluster manager service is not available"); | ||
msfroh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
82 changes: 82 additions & 0 deletions
82
server/src/main/java/org/opensearch/discovery/LocalDiscovery.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| /* | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| * | ||
| * The OpenSearch Contributors require contributions made to | ||
| * this file be licensed under the Apache-2.0 license or a | ||
| * compatible open source license. | ||
| */ | ||
|
|
||
| package org.opensearch.discovery; | ||
|
|
||
| import org.opensearch.cluster.ClusterChangedEvent; | ||
| import org.opensearch.cluster.ClusterState; | ||
| import org.opensearch.cluster.NodeConnectionsService; | ||
| import org.opensearch.cluster.coordination.PendingClusterStateStats; | ||
| import org.opensearch.cluster.coordination.PublishClusterStateStats; | ||
| import org.opensearch.cluster.node.DiscoveryNode; | ||
| import org.opensearch.cluster.node.DiscoveryNodes; | ||
| import org.opensearch.cluster.service.ClusterApplier; | ||
| import org.opensearch.cluster.service.ClusterStateStats; | ||
| import org.opensearch.common.lifecycle.AbstractLifecycleComponent; | ||
| import org.opensearch.core.action.ActionListener; | ||
| import org.opensearch.transport.TransportService; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| /** | ||
| * Clusterless implementation of Discovery. This is only able to "discover" the local node. | ||
| */ | ||
| public class LocalDiscovery extends AbstractLifecycleComponent implements Discovery { | ||
| private static final DiscoveryStats EMPTY_STATS = new DiscoveryStats( | ||
| new PendingClusterStateStats(0, 0, 0), | ||
| new PublishClusterStateStats(0, 0, 0), | ||
| new ClusterStateStats() | ||
| ); | ||
| private final TransportService transportService; | ||
| private final ClusterApplier clusterApplier; | ||
|
|
||
| public LocalDiscovery(TransportService transportService, ClusterApplier clusterApplier) { | ||
| this.transportService = transportService; | ||
| this.clusterApplier = clusterApplier; | ||
| } | ||
|
|
||
| @Override | ||
| public void publish(ClusterChangedEvent clusterChangedEvent, ActionListener<Void> publishListener, AckListener ackListener) { | ||
| // In clusterless mode, we should never be asked to publish a cluster state. | ||
| throw new UnsupportedOperationException("Should not be called in clusterless mode"); | ||
| } | ||
|
|
||
| @Override | ||
| protected void doStart() { | ||
| DiscoveryNode localNode = transportService.getLocalNode(); | ||
| ClusterState bootstrapClusterState = ClusterState.builder(ClusterState.EMPTY_STATE) | ||
msfroh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .nodes(DiscoveryNodes.builder().localNodeId(localNode.getId()).add(localNode).build()) | ||
msfroh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .build(); | ||
| clusterApplier.setInitialState(bootstrapClusterState); | ||
| } | ||
|
|
||
| @Override | ||
| protected void doStop() { | ||
|
|
||
| } | ||
|
|
||
| @Override | ||
| protected void doClose() throws IOException { | ||
|
|
||
| } | ||
|
|
||
| @Override | ||
| public DiscoveryStats stats() { | ||
| return EMPTY_STATS; | ||
| } | ||
|
|
||
| @Override | ||
| public void startInitialJoin() { | ||
|
|
||
| } | ||
|
|
||
| @Override | ||
| public void setNodeConnectionsService(NodeConnectionsService nodeConnectionsService) { | ||
|
|
||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.