Skip to content

Commit 21d91f1

Browse files
authored
[Zen2] Respect the no_master_block setting (#36478)
Today the Zen2 coordinator only applies a write block when there is no known elected master, ignoring the `discovery.zen.no_master_block` setting. This commit resolves this, applying the correct block according to the configuration instead.
1 parent 084e06e commit 21d91f1

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

server/src/main/java/org/elasticsearch/cluster/coordination/Coordinator.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
import java.util.stream.StreamSupport;
8282

8383
import static org.elasticsearch.common.util.concurrent.ConcurrentCollections.newConcurrentSet;
84-
import static org.elasticsearch.discovery.DiscoverySettings.NO_MASTER_BLOCK_WRITES;
84+
import static org.elasticsearch.discovery.DiscoverySettings.NO_MASTER_BLOCK_ID;
8585
import static org.elasticsearch.gateway.ClusterStateUpdaters.hideStateIfNotRecovered;
8686
import static org.elasticsearch.gateway.GatewayService.STATE_NOT_RECOVERED_BLOCK;
8787

@@ -102,6 +102,7 @@ public class Coordinator extends AbstractLifecycleComponent implements Discovery
102102
private final JoinHelper joinHelper;
103103
private final NodeRemovalClusterStateTaskExecutor nodeRemovalExecutor;
104104
private final Supplier<CoordinationState.PersistedState> persistedStateSupplier;
105+
private final DiscoverySettings discoverySettings;
105106
// TODO: the following two fields are package-private as some tests require access to them
106107
// These tests can be rewritten to use public methods once Coordinator is more feature-complete
107108
final Object mutex = new Object();
@@ -147,6 +148,7 @@ public Coordinator(String nodeName, Settings settings, ClusterSettings clusterSe
147148
this.joinHelper = new JoinHelper(settings, allocationService, masterService, transportService,
148149
this::getCurrentTerm, this::handleJoinRequest, this::joinLeaderInTerm);
149150
this.persistedStateSupplier = persistedStateSupplier;
151+
this.discoverySettings = new DiscoverySettings(settings, clusterSettings);
150152
this.lastKnownLeader = Optional.empty();
151153
this.lastJoin = Optional.empty();
152154
this.joinAccumulator = new InitialJoinAccumulator();
@@ -528,7 +530,7 @@ protected void doStart() {
528530
ClusterState initialState = ClusterState.builder(ClusterName.CLUSTER_NAME_SETTING.get(settings))
529531
.blocks(ClusterBlocks.builder()
530532
.addGlobalBlock(STATE_NOT_RECOVERED_BLOCK)
531-
.addGlobalBlock(NO_MASTER_BLOCK_WRITES)) // TODO: allow dynamically configuring NO_MASTER_BLOCK_ALL
533+
.addGlobalBlock(discoverySettings.getNoMasterBlock()))
532534
.nodes(DiscoveryNodes.builder().add(getLocalNode()).localNodeId(getLocalNode().getId()))
533535
.build();
534536
applierState = initialState;
@@ -568,7 +570,7 @@ public void invariant() {
568570
assert peerFinder.getCurrentTerm() == getCurrentTerm();
569571
assert followersChecker.getFastResponseState().term == getCurrentTerm() : followersChecker.getFastResponseState();
570572
assert followersChecker.getFastResponseState().mode == getMode() : followersChecker.getFastResponseState();
571-
assert (applierState.nodes().getMasterNodeId() == null) == applierState.blocks().hasGlobalBlock(NO_MASTER_BLOCK_WRITES.id());
573+
assert (applierState.nodes().getMasterNodeId() == null) == applierState.blocks().hasGlobalBlock(NO_MASTER_BLOCK_ID);
572574
assert preVoteCollector.getPreVoteResponse().equals(getPreVoteResponse())
573575
: preVoteCollector + " vs " + getPreVoteResponse();
574576

@@ -873,11 +875,10 @@ ClusterState getStateForMasterService() {
873875
private ClusterState clusterStateWithNoMasterBlock(ClusterState clusterState) {
874876
if (clusterState.nodes().getMasterNodeId() != null) {
875877
// remove block if it already exists before adding new one
876-
assert clusterState.blocks().hasGlobalBlock(DiscoverySettings.NO_MASTER_BLOCK_ID) == false :
878+
assert clusterState.blocks().hasGlobalBlock(NO_MASTER_BLOCK_ID) == false :
877879
"NO_MASTER_BLOCK should only be added by Coordinator";
878-
// TODO: allow dynamically configuring NO_MASTER_BLOCK_ALL
879880
final ClusterBlocks clusterBlocks = ClusterBlocks.builder().blocks(clusterState.blocks()).addGlobalBlock(
880-
NO_MASTER_BLOCK_WRITES).build();
881+
discoverySettings.getNoMasterBlock()).build();
881882
final DiscoveryNodes discoveryNodes = new DiscoveryNodes.Builder(clusterState.nodes()).masterNodeId(null).build();
882883
return ClusterState.builder(clusterState).blocks(clusterBlocks).nodes(discoveryNodes).build();
883884
} else {

server/src/test/java/org/elasticsearch/cluster/coordination/CoordinatorTests.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.elasticsearch.cluster.ClusterState;
3030
import org.elasticsearch.cluster.ClusterStateUpdateTask;
3131
import org.elasticsearch.cluster.ESAllocationTestCase;
32+
import org.elasticsearch.cluster.block.ClusterBlock;
3233
import org.elasticsearch.cluster.coordination.ClusterStatePublisher.AckListener;
3334
import org.elasticsearch.cluster.coordination.CoordinationMetaData.VotingConfiguration;
3435
import org.elasticsearch.cluster.coordination.CoordinationState.PersistedState;
@@ -44,6 +45,7 @@
4445
import org.elasticsearch.common.settings.ClusterSettings;
4546
import org.elasticsearch.common.settings.Setting;
4647
import org.elasticsearch.common.settings.Settings;
48+
import org.elasticsearch.common.settings.Settings.Builder;
4749
import org.elasticsearch.common.transport.TransportAddress;
4850
import org.elasticsearch.common.unit.TimeValue;
4951
import org.elasticsearch.discovery.zen.PublishClusterStateStats;
@@ -95,11 +97,15 @@
9597
import static org.elasticsearch.cluster.coordination.LeaderChecker.LEADER_CHECK_RETRY_COUNT_SETTING;
9698
import static org.elasticsearch.cluster.coordination.LeaderChecker.LEADER_CHECK_TIMEOUT_SETTING;
9799
import static org.elasticsearch.cluster.coordination.Reconfigurator.CLUSTER_AUTO_SHRINK_VOTING_CONFIGURATION;
100+
import static org.elasticsearch.discovery.DiscoverySettings.NO_MASTER_BLOCK_ALL;
98101
import static org.elasticsearch.discovery.DiscoverySettings.NO_MASTER_BLOCK_ID;
102+
import static org.elasticsearch.discovery.DiscoverySettings.NO_MASTER_BLOCK_SETTING;
103+
import static org.elasticsearch.discovery.DiscoverySettings.NO_MASTER_BLOCK_WRITES;
99104
import static org.elasticsearch.discovery.PeerFinder.DISCOVERY_FIND_PEERS_INTERVAL_SETTING;
100105
import static org.elasticsearch.node.Node.NODE_NAME_SETTING;
101106
import static org.elasticsearch.transport.TransportService.HANDSHAKE_ACTION_NAME;
102107
import static org.elasticsearch.transport.TransportService.NOOP_TRANSPORT_INTERCEPTOR;
108+
import static org.hamcrest.Matchers.contains;
103109
import static org.hamcrest.Matchers.containsString;
104110
import static org.hamcrest.Matchers.empty;
105111
import static org.hamcrest.Matchers.endsWith;
@@ -914,6 +920,39 @@ public void testStayCandidateAfterReceivingFollowerCheckFromKnownMaster() {
914920
cluster.stabilise();
915921
}
916922

923+
public void testAppliesNoMasterBlockWritesByDefault() {
924+
testAppliesNoMasterBlock(null, NO_MASTER_BLOCK_WRITES);
925+
}
926+
927+
public void testAppliesNoMasterBlockWritesIfConfigured() {
928+
testAppliesNoMasterBlock("write", NO_MASTER_BLOCK_WRITES);
929+
}
930+
931+
public void testAppliesNoMasterBlockAllIfConfigured() {
932+
testAppliesNoMasterBlock("all", NO_MASTER_BLOCK_ALL);
933+
}
934+
935+
private void testAppliesNoMasterBlock(String noMasterBlockSetting, ClusterBlock expectedBlock) {
936+
final Cluster cluster = new Cluster(3);
937+
cluster.runRandomly();
938+
cluster.stabilise();
939+
940+
final ClusterNode leader = cluster.getAnyLeader();
941+
leader.submitUpdateTask("update NO_MASTER_BLOCK_SETTING", cs -> {
942+
final Builder settingsBuilder = Settings.builder().put(cs.metaData().persistentSettings());
943+
settingsBuilder.put(NO_MASTER_BLOCK_SETTING.getKey(), noMasterBlockSetting);
944+
return ClusterState.builder(cs).metaData(MetaData.builder(cs.metaData()).persistentSettings(settingsBuilder.build())).build();
945+
});
946+
cluster.runFor(DEFAULT_CLUSTER_STATE_UPDATE_DELAY, "committing setting update");
947+
948+
leader.disconnect();
949+
cluster.runFor(defaultMillis(FOLLOWER_CHECK_INTERVAL_SETTING) + DEFAULT_CLUSTER_STATE_UPDATE_DELAY, "detecting disconnection");
950+
951+
assertThat(leader.clusterApplier.lastAppliedClusterState.blocks().global(), contains(expectedBlock));
952+
953+
// TODO reboot the leader and verify that the same block is applied when it restarts
954+
}
955+
917956
private static long defaultMillis(Setting<TimeValue> setting) {
918957
return setting.get(Settings.EMPTY).millis() + Cluster.DEFAULT_DELAY_VARIABILITY;
919958
}

0 commit comments

Comments
 (0)