23
23
import org .apache .logging .log4j .Logger ;
24
24
import org .apache .logging .log4j .message .ParameterizedMessage ;
25
25
import org .elasticsearch .ElasticsearchException ;
26
+ import org .elasticsearch .Version ;
26
27
import org .elasticsearch .cluster .ClusterName ;
27
28
import org .elasticsearch .cluster .ClusterState ;
28
- import org .elasticsearch .cluster .coordination .CoordinationMetaData .VotingConfiguration ;
29
29
import org .elasticsearch .cluster .ClusterStateUpdateTask ;
30
30
import org .elasticsearch .cluster .ESAllocationTestCase ;
31
31
import org .elasticsearch .cluster .coordination .ClusterStatePublisher .AckListener ;
32
+ import org .elasticsearch .cluster .coordination .CoordinationMetaData .VotingConfiguration ;
32
33
import org .elasticsearch .cluster .coordination .CoordinationState .PersistedState ;
33
34
import org .elasticsearch .cluster .coordination .Coordinator .Mode ;
34
35
import org .elasticsearch .cluster .coordination .CoordinatorTests .Cluster .ClusterNode ;
35
36
import org .elasticsearch .cluster .metadata .MetaData ;
36
37
import org .elasticsearch .cluster .node .DiscoveryNode ;
38
+ import org .elasticsearch .cluster .node .DiscoveryNode .Role ;
37
39
import org .elasticsearch .cluster .service .ClusterApplier ;
38
40
import org .elasticsearch .common .Randomness ;
41
+ import org .elasticsearch .common .UUIDs ;
39
42
import org .elasticsearch .common .lease .Releasable ;
40
43
import org .elasticsearch .common .settings .ClusterSettings ;
41
44
import org .elasticsearch .common .settings .Setting ;
58
61
import java .util .ArrayList ;
59
62
import java .util .Arrays ;
60
63
import java .util .Collections ;
64
+ import java .util .EnumSet ;
61
65
import java .util .HashMap ;
62
66
import java .util .HashSet ;
63
67
import java .util .List ;
@@ -136,6 +140,15 @@ public void testCanUpdateClusterStateAfterStabilisation() {
136
140
}
137
141
}
138
142
143
+ public void testDoesNotElectNonMasterNode () {
144
+ final Cluster cluster = new Cluster (randomIntBetween (1 , 5 ), false );
145
+ cluster .runRandomly ();
146
+ cluster .stabilise ();
147
+
148
+ final ClusterNode leader = cluster .getAnyLeader ();
149
+ assertTrue (leader .localNode .isMasterNode ());
150
+ }
151
+
139
152
public void testNodesJoinAfterStableCluster () {
140
153
final Cluster cluster = new Cluster (randomIntBetween (1 , 5 ));
141
154
cluster .runRandomly ();
@@ -889,10 +902,6 @@ private static int defaultInt(Setting<Integer> setting) {
889
902
// then wait for the new leader to commit a state without the old leader
890
903
+ DEFAULT_CLUSTER_STATE_UPDATE_DELAY ;
891
904
892
- private static String nodeIdFromIndex (int nodeIndex ) {
893
- return "node" + nodeIndex ;
894
- }
895
-
896
905
class Cluster {
897
906
898
907
static final long EXTREME_DELAY_VARIABILITY = 10000L ;
@@ -910,26 +919,29 @@ class Cluster {
910
919
private final Map <Long , ClusterState > committedStatesByVersion = new HashMap <>();
911
920
912
921
Cluster (int initialNodeCount ) {
922
+ this (initialNodeCount , true );
923
+ }
924
+
925
+ Cluster (int initialNodeCount , boolean allNodesMasterEligible ) {
913
926
deterministicTaskQueue .setExecutionDelayVariabilityMillis (DEFAULT_DELAY_VARIABILITY );
914
927
915
928
assertThat (initialNodeCount , greaterThan (0 ));
916
929
917
- final Set <String > initialConfigurationNodeIds = new HashSet <>(initialNodeCount );
918
- while (initialConfigurationNodeIds .isEmpty ()) {
919
- for (int i = 0 ; i < initialNodeCount ; i ++) {
920
- if (randomBoolean ()) {
921
- initialConfigurationNodeIds .add (nodeIdFromIndex (i ));
922
- }
923
- }
924
- }
925
- initialConfiguration = new VotingConfiguration (initialConfigurationNodeIds );
926
- logger .info ("--> creating cluster of {} nodes with initial configuration {}" , initialNodeCount , initialConfiguration );
927
-
930
+ final Set <String > masterEligibleNodeIds = new HashSet <>(initialNodeCount );
928
931
clusterNodes = new ArrayList <>(initialNodeCount );
929
932
for (int i = 0 ; i < initialNodeCount ; i ++) {
930
- final ClusterNode clusterNode = new ClusterNode (i );
933
+ final ClusterNode clusterNode = new ClusterNode (i , allNodesMasterEligible || i == 0 || randomBoolean () );
931
934
clusterNodes .add (clusterNode );
935
+ if (clusterNode .getLocalNode ().isMasterNode ()) {
936
+ masterEligibleNodeIds .add (clusterNode .getId ());
937
+ }
932
938
}
939
+
940
+ initialConfiguration = new VotingConfiguration (new HashSet <>(
941
+ randomSubsetOf (randomIntBetween (1 , masterEligibleNodeIds .size ()), masterEligibleNodeIds )));
942
+
943
+ logger .info ("--> creating cluster of {} nodes (master-eligible nodes: {}) with initial configuration {}" ,
944
+ initialNodeCount , masterEligibleNodeIds , initialConfiguration );
933
945
}
934
946
935
947
void addNodesAndStabilise (int newNodesCount ) {
@@ -950,7 +962,7 @@ void addNodes(int newNodesCount) {
950
962
951
963
final int nodeSizeAtStart = clusterNodes .size ();
952
964
for (int i = 0 ; i < newNodesCount ; i ++) {
953
- final ClusterNode clusterNode = new ClusterNode (nodeSizeAtStart + i );
965
+ final ClusterNode clusterNode = new ClusterNode (nodeSizeAtStart + i , true );
954
966
clusterNodes .add (clusterNode );
955
967
}
956
968
}
@@ -1090,11 +1102,11 @@ void stabilise(long stabilisationDurationMillis) {
1090
1102
deterministicTaskQueue .getExecutionDelayVariabilityMillis (), lessThanOrEqualTo (DEFAULT_DELAY_VARIABILITY ));
1091
1103
assertFalse ("stabilisation requires stable storage" , disruptStorage );
1092
1104
1093
- if (clusterNodes .stream ().allMatch (n -> n . coordinator . isInitialConfigurationSet () == false )) {
1105
+ if (clusterNodes .stream ().allMatch (ClusterNode :: isNotUsefullyBootstrapped )) {
1094
1106
assertThat ("setting initial configuration may fail with disconnected nodes" , disconnectedNodes , empty ());
1095
1107
assertThat ("setting initial configuration may fail with blackholed nodes" , blackholedNodes , empty ());
1096
1108
runFor (defaultMillis (DISCOVERY_FIND_PEERS_INTERVAL_SETTING ) * 2 , "discovery prior to setting initial configuration" );
1097
- final ClusterNode bootstrapNode = getAnyNode ();
1109
+ final ClusterNode bootstrapNode = getAnyMasterEligibleNode ();
1098
1110
bootstrapNode .applyInitialConfiguration ();
1099
1111
} else {
1100
1112
logger .info ("setting initial configuration not required" );
@@ -1211,6 +1223,10 @@ private ConnectionStatus getConnectionStatus(DiscoveryNode sender, DiscoveryNode
1211
1223
return connectionStatus ;
1212
1224
}
1213
1225
1226
+ ClusterNode getAnyMasterEligibleNode () {
1227
+ return randomFrom (clusterNodes .stream ().filter (n -> n .getLocalNode ().isMasterNode ()).collect (Collectors .toList ()));
1228
+ }
1229
+
1214
1230
ClusterNode getAnyNode () {
1215
1231
return getAnyNodeExcept ();
1216
1232
}
@@ -1283,16 +1299,20 @@ class ClusterNode {
1283
1299
private DisruptableMockTransport mockTransport ;
1284
1300
private ClusterStateApplyResponse clusterStateApplyResponse = ClusterStateApplyResponse .SUCCEED ;
1285
1301
1286
- ClusterNode (int nodeIndex ) {
1302
+ ClusterNode (int nodeIndex , boolean masterEligible ) {
1287
1303
this .nodeIndex = nodeIndex ;
1288
- localNode = createDiscoveryNode ();
1304
+ localNode = createDiscoveryNode (masterEligible );
1289
1305
persistedState = new MockPersistedState (0L ,
1290
1306
clusterState (0L , 0L , localNode , VotingConfiguration .EMPTY_CONFIG , VotingConfiguration .EMPTY_CONFIG , 0L ));
1291
1307
onNode (localNode , this ::setUp ).run ();
1292
1308
}
1293
1309
1294
- private DiscoveryNode createDiscoveryNode () {
1295
- return CoordinationStateTests .createNode (nodeIdFromIndex (nodeIndex ));
1310
+ private DiscoveryNode createDiscoveryNode (boolean masterEligible ) {
1311
+ final TransportAddress address = buildNewFakeTransportAddress ();
1312
+ return new DiscoveryNode ("" , "node" + nodeIndex ,
1313
+ UUIDs .randomBase64UUID (random ()), // generated deterministically for repeatable tests
1314
+ address .address ().getHostString (), address .getAddress (), address , Collections .emptyMap (),
1315
+ masterEligible ? EnumSet .allOf (Role .class ) : emptySet (), Version .CURRENT );
1296
1316
}
1297
1317
1298
1318
private void setUp () {
@@ -1483,6 +1503,10 @@ void applyInitialConfiguration() {
1483
1503
}).run ();
1484
1504
}
1485
1505
1506
+ private boolean isNotUsefullyBootstrapped () {
1507
+ return getLocalNode ().isMasterNode () == false || coordinator .isInitialConfigurationSet () == false ;
1508
+ }
1509
+
1486
1510
private class FakeClusterApplier implements ClusterApplier {
1487
1511
1488
1512
final ClusterName clusterName ;
0 commit comments