use of org.opensearch.cluster.service.MasterService in project OpenSearch by opensearch-project.
the class NodeJoinTests method setupRealMasterServiceAndCoordinator.
private void setupRealMasterServiceAndCoordinator(long term, ClusterState initialState) {
MasterService masterService = new MasterService(Settings.builder().put(Node.NODE_NAME_SETTING.getKey(), "test_node").build(), new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS), threadPool);
AtomicReference<ClusterState> clusterStateRef = new AtomicReference<>(initialState);
masterService.setClusterStatePublisher((event, publishListener, ackListener) -> {
clusterStateRef.set(event.state());
publishListener.onResponse(null);
});
setupMasterServiceAndCoordinator(term, initialState, masterService, threadPool, new Random(Randomness.get().nextLong()), () -> new StatusInfo(HEALTHY, "healthy-info"));
masterService.setClusterStateSupplier(clusterStateRef::get);
masterService.start();
}
use of org.opensearch.cluster.service.MasterService in project OpenSearch by opensearch-project.
the class NodeJoinTests method setupMasterServiceAndCoordinator.
private void setupMasterServiceAndCoordinator(long term, ClusterState initialState, MasterService masterService, ThreadPool threadPool, Random random, NodeHealthService nodeHealthService) {
if (this.masterService != null || coordinator != null) {
throw new IllegalStateException("method setupMasterServiceAndCoordinator can only be called once");
}
this.masterService = masterService;
CapturingTransport capturingTransport = new CapturingTransport() {
@Override
protected void onSendRequest(long requestId, String action, TransportRequest request, DiscoveryNode destination) {
if (action.equals(HANDSHAKE_ACTION_NAME)) {
handleResponse(requestId, new TransportService.HandshakeResponse(destination, initialState.getClusterName(), destination.getVersion()));
} else if (action.equals(JoinHelper.VALIDATE_JOIN_ACTION_NAME)) {
handleResponse(requestId, new TransportResponse.Empty());
} else {
super.onSendRequest(requestId, action, request, destination);
}
}
};
final ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
TransportService transportService = capturingTransport.createTransportService(Settings.EMPTY, threadPool, TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> initialState.nodes().getLocalNode(), clusterSettings, Collections.emptySet());
coordinator = new Coordinator("test_node", Settings.EMPTY, clusterSettings, transportService, writableRegistry(), OpenSearchAllocationTestCase.createAllocationService(Settings.EMPTY), masterService, () -> new InMemoryPersistedState(term, initialState), r -> emptyList(), new NoOpClusterApplier(), Collections.emptyList(), random, (s, p, r) -> {
}, ElectionStrategy.DEFAULT_INSTANCE, nodeHealthService);
transportService.start();
transportService.acceptIncomingRequests();
transport = capturingTransport;
coordinator.start();
coordinator.startInitialJoin();
}
use of org.opensearch.cluster.service.MasterService in project OpenSearch by opensearch-project.
the class NodeJoinTests method testConcurrentJoining.
public void testConcurrentJoining() {
List<DiscoveryNode> masterNodes = IntStream.rangeClosed(1, randomIntBetween(2, 5)).mapToObj(nodeId -> newNode(nodeId, true)).collect(Collectors.toList());
List<DiscoveryNode> otherNodes = IntStream.rangeClosed(masterNodes.size() + 1, masterNodes.size() + 1 + randomIntBetween(0, 5)).mapToObj(nodeId -> newNode(nodeId, false)).collect(Collectors.toList());
List<DiscoveryNode> allNodes = Stream.concat(masterNodes.stream(), otherNodes.stream()).collect(Collectors.toList());
DiscoveryNode localNode = masterNodes.get(0);
VotingConfiguration votingConfiguration = new VotingConfiguration(randomValueOtherThan(singletonList(localNode), () -> randomSubsetOf(randomIntBetween(1, masterNodes.size()), masterNodes)).stream().map(DiscoveryNode::getId).collect(Collectors.toSet()));
logger.info("Voting configuration: {}", votingConfiguration);
long initialTerm = randomLongBetween(1, 10);
long initialVersion = randomLongBetween(1, 10);
setupRealMasterServiceAndCoordinator(initialTerm, initialState(localNode, initialTerm, initialVersion, votingConfiguration));
long newTerm = initialTerm + randomLongBetween(1, 10);
// we need at least a quorum of voting nodes with a correct term and worse state
List<DiscoveryNode> successfulNodes;
do {
successfulNodes = randomSubsetOf(allNodes);
} while (votingConfiguration.hasQuorum(successfulNodes.stream().map(DiscoveryNode::getId).collect(Collectors.toList())) == false);
logger.info("Successful voting nodes: {}", successfulNodes);
List<JoinRequest> correctJoinRequests = successfulNodes.stream().map(node -> new JoinRequest(node, newTerm, Optional.of(new Join(node, localNode, newTerm, initialTerm, initialVersion)))).collect(Collectors.toList());
List<DiscoveryNode> possiblyUnsuccessfulNodes = new ArrayList<>(allNodes);
possiblyUnsuccessfulNodes.removeAll(successfulNodes);
logger.info("Possibly unsuccessful voting nodes: {}", possiblyUnsuccessfulNodes);
List<JoinRequest> possiblyFailingJoinRequests = possiblyUnsuccessfulNodes.stream().map(node -> {
if (randomBoolean()) {
// a correct request
return new JoinRequest(node, newTerm, Optional.of(new Join(node, localNode, newTerm, initialTerm, initialVersion)));
} else if (randomBoolean()) {
// term too low
return new JoinRequest(node, newTerm, Optional.of(new Join(node, localNode, randomLongBetween(0, initialTerm), initialTerm, initialVersion)));
} else {
// better state
return new JoinRequest(node, newTerm, Optional.of(new Join(node, localNode, newTerm, initialTerm, initialVersion + randomLongBetween(1, 10))));
}
}).collect(Collectors.toList());
// duplicate some requests, which will be unsuccessful
possiblyFailingJoinRequests.addAll(randomSubsetOf(possiblyFailingJoinRequests));
CyclicBarrier barrier = new CyclicBarrier(correctJoinRequests.size() + possiblyFailingJoinRequests.size() + 1);
final Runnable awaitBarrier = () -> {
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
};
final AtomicBoolean stopAsserting = new AtomicBoolean();
final Thread assertionThread = new Thread(() -> {
awaitBarrier.run();
while (stopAsserting.get() == false) {
coordinator.invariant();
}
}, "assert invariants");
final List<Thread> joinThreads = Stream.concat(correctJoinRequests.stream().map(joinRequest -> new Thread(() -> {
awaitBarrier.run();
joinNode(joinRequest);
}, "process " + joinRequest)), possiblyFailingJoinRequests.stream().map(joinRequest -> new Thread(() -> {
awaitBarrier.run();
try {
joinNode(joinRequest);
} catch (CoordinationStateRejectedException e) {
// ignore - these requests are expected to fail
}
}, "process " + joinRequest))).collect(Collectors.toList());
assertionThread.start();
joinThreads.forEach(Thread::start);
joinThreads.forEach(t -> {
try {
t.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
stopAsserting.set(true);
try {
assertionThread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
assertTrue(MasterServiceTests.discoveryState(masterService).nodes().isLocalNodeElectedMaster());
for (DiscoveryNode successfulNode : successfulNodes) {
assertTrue(successfulNode + " joined cluster", clusterStateHasNode(successfulNode));
assertFalse(successfulNode + " voted for master", coordinator.missingJoinVoteFrom(successfulNode));
}
}
use of org.opensearch.cluster.service.MasterService in project OpenSearch by opensearch-project.
the class ClusterServiceUtils method createMasterService.
public static MasterService createMasterService(ThreadPool threadPool, ClusterState initialClusterState) {
MasterService masterService = new MasterService(Settings.builder().put(Node.NODE_NAME_SETTING.getKey(), "test_master_node").build(), new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS), threadPool);
AtomicReference<ClusterState> clusterStateRef = new AtomicReference<>(initialClusterState);
masterService.setClusterStatePublisher((event, publishListener, ackListener) -> {
clusterStateRef.set(event.state());
publishListener.onResponse(null);
});
masterService.setClusterStateSupplier(clusterStateRef::get);
masterService.start();
return masterService;
}
use of org.opensearch.cluster.service.MasterService in project OpenSearch by opensearch-project.
the class InternalClusterInfoServiceSchedulingTests method testScheduling.
public void testScheduling() {
final DiscoveryNode discoveryNode = new DiscoveryNode("test", buildNewFakeTransportAddress(), Version.CURRENT);
final DiscoveryNodes noMaster = DiscoveryNodes.builder().add(discoveryNode).localNodeId(discoveryNode.getId()).build();
final DiscoveryNodes localMaster = DiscoveryNodes.builder(noMaster).masterNodeId(discoveryNode.getId()).build();
final Settings.Builder settingsBuilder = Settings.builder().put(Node.NODE_NAME_SETTING.getKey(), discoveryNode.getName());
if (randomBoolean()) {
settingsBuilder.put(INTERNAL_CLUSTER_INFO_UPDATE_INTERVAL_SETTING.getKey(), randomIntBetween(10000, 60000) + "ms");
}
final Settings settings = settingsBuilder.build();
final ClusterSettings clusterSettings = new ClusterSettings(settings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
final DeterministicTaskQueue deterministicTaskQueue = new DeterministicTaskQueue(settings, random());
final ThreadPool threadPool = deterministicTaskQueue.getThreadPool();
final ClusterApplierService clusterApplierService = new ClusterApplierService("test", settings, clusterSettings, threadPool) {
@Override
protected PrioritizedOpenSearchThreadPoolExecutor createThreadPoolExecutor() {
return new MockSinglePrioritizingExecutor("mock-executor", deterministicTaskQueue, threadPool);
}
};
final MasterService masterService = new FakeThreadPoolMasterService("test", "masterService", threadPool, r -> {
fail("master service should not run any tasks");
});
final ClusterService clusterService = new ClusterService(settings, clusterSettings, masterService, clusterApplierService);
final FakeClusterInfoServiceClient client = new FakeClusterInfoServiceClient(threadPool);
final InternalClusterInfoService clusterInfoService = new InternalClusterInfoService(settings, clusterService, threadPool, client);
clusterService.addListener(clusterInfoService);
clusterInfoService.addListener(ignored -> {
});
clusterService.setNodeConnectionsService(ClusterServiceUtils.createNoOpNodeConnectionsService());
clusterApplierService.setInitialState(ClusterState.builder(new ClusterName("cluster")).nodes(noMaster).build());
masterService.setClusterStatePublisher((clusterChangedEvent, publishListener, ackListener) -> fail("should not publish"));
masterService.setClusterStateSupplier(clusterApplierService::state);
clusterService.start();
final AtomicBoolean becameMaster1 = new AtomicBoolean();
clusterApplierService.onNewClusterState("become master 1", () -> ClusterState.builder(new ClusterName("cluster")).nodes(localMaster).build(), setFlagOnSuccess(becameMaster1));
runUntilFlag(deterministicTaskQueue, becameMaster1);
final AtomicBoolean failMaster1 = new AtomicBoolean();
clusterApplierService.onNewClusterState("fail master 1", () -> ClusterState.builder(new ClusterName("cluster")).nodes(noMaster).build(), setFlagOnSuccess(failMaster1));
runUntilFlag(deterministicTaskQueue, failMaster1);
final AtomicBoolean becameMaster2 = new AtomicBoolean();
clusterApplierService.onNewClusterState("become master 2", () -> ClusterState.builder(new ClusterName("cluster")).nodes(localMaster).build(), setFlagOnSuccess(becameMaster2));
runUntilFlag(deterministicTaskQueue, becameMaster2);
for (int i = 0; i < 3; i++) {
final int initialRequestCount = client.requestCount;
final long duration = INTERNAL_CLUSTER_INFO_UPDATE_INTERVAL_SETTING.get(settings).millis();
runFor(deterministicTaskQueue, duration);
deterministicTaskQueue.runAllRunnableTasks();
// should have run two client requests per interval
assertThat(client.requestCount, equalTo(initialRequestCount + 2));
}
final AtomicBoolean failMaster2 = new AtomicBoolean();
clusterApplierService.onNewClusterState("fail master 2", () -> ClusterState.builder(new ClusterName("cluster")).nodes(noMaster).build(), setFlagOnSuccess(failMaster2));
runUntilFlag(deterministicTaskQueue, failMaster2);
runFor(deterministicTaskQueue, INTERNAL_CLUSTER_INFO_UPDATE_INTERVAL_SETTING.get(settings).millis());
deterministicTaskQueue.runAllRunnableTasks();
assertFalse(deterministicTaskQueue.hasRunnableTasks());
assertFalse(deterministicTaskQueue.hasDeferredTasks());
}
Aggregations