2020package org .elasticsearch .cluster .metadata ;
2121
2222import org .elasticsearch .Version ;
23+ import org .elasticsearch .action .support .master .AcknowledgedResponse ;
2324import org .elasticsearch .cluster .ClusterName ;
2425import org .elasticsearch .cluster .ClusterState ;
26+ import org .elasticsearch .cluster .RestoreInProgress ;
27+ import org .elasticsearch .cluster .SnapshotsInProgress ;
28+ import org .elasticsearch .cluster .block .ClusterBlock ;
29+ import org .elasticsearch .cluster .block .ClusterBlocks ;
2530import org .elasticsearch .cluster .node .DiscoveryNode ;
2631import org .elasticsearch .cluster .node .DiscoveryNodes ;
32+ import org .elasticsearch .cluster .routing .IndexRoutingTable ;
33+ import org .elasticsearch .cluster .routing .IndexShardRoutingTable ;
34+ import org .elasticsearch .cluster .routing .RoutingTable ;
35+ import org .elasticsearch .cluster .routing .ShardRouting ;
36+ import org .elasticsearch .cluster .routing .ShardRoutingState ;
2737import org .elasticsearch .cluster .shards .ClusterShardLimitIT ;
38+ import org .elasticsearch .common .Nullable ;
2839import org .elasticsearch .common .ValidationException ;
2940import org .elasticsearch .common .collect .ImmutableOpenMap ;
30- import org .elasticsearch .common .logging .DeprecationLogger ;
3141import org .elasticsearch .common .settings .Settings ;
3242import org .elasticsearch .index .Index ;
43+ import org .elasticsearch .index .IndexNotFoundException ;
44+ import org .elasticsearch .index .shard .ShardId ;
45+ import org .elasticsearch .repositories .IndexId ;
46+ import org .elasticsearch .snapshots .Snapshot ;
47+ import org .elasticsearch .snapshots .SnapshotId ;
3348import org .elasticsearch .test .ESTestCase ;
3449
3550import java .util .Arrays ;
51+ import java .util .Collections ;
52+ import java .util .HashMap ;
53+ import java .util .HashSet ;
54+ import java .util .Map ;
55+ import java .util .Set ;
3656import java .util .stream .Collectors ;
3757
58+ import static org .elasticsearch .cluster .metadata .IndexMetaData .SETTING_NUMBER_OF_REPLICAS ;
59+ import static org .elasticsearch .cluster .metadata .IndexMetaData .SETTING_NUMBER_OF_SHARDS ;
60+ import static org .elasticsearch .cluster .metadata .IndexMetaData .SETTING_VERSION_CREATED ;
61+ import static org .elasticsearch .cluster .routing .TestShardRouting .newShardRouting ;
3862import static org .elasticsearch .cluster .shards .ClusterShardLimitIT .ShardCounts .forDataNodeCount ;
63+ import static org .hamcrest .Matchers .containsString ;
64+ import static org .hamcrest .Matchers .equalTo ;
65+ import static org .hamcrest .Matchers .is ;
66+ import static org .hamcrest .Matchers .notNullValue ;
67+ import static org .hamcrest .Matchers .nullValue ;
3968import static org .mockito .Mockito .mock ;
4069import static org .mockito .Mockito .when ;
4170
4271public class MetaDataIndexStateServiceTests extends ESTestCase {
4372
73+ public void testCloseRoutingTable () {
74+ final Set <Index > nonBlockedIndices = new HashSet <>();
75+ final Map <Index , AcknowledgedResponse > blockedIndices = new HashMap <>();
76+
77+ ClusterState state = ClusterState .builder (new ClusterName ("testCloseRoutingTable" )).build ();
78+ for (int i = 0 ; i < randomIntBetween (1 , 25 ); i ++) {
79+ final String indexName = randomAlphaOfLengthBetween (5 , 15 );
80+
81+ if (randomBoolean ()) {
82+ state = addOpenedIndex (indexName , randomIntBetween (1 , 5 ), randomIntBetween (0 , 5 ), state );
83+ nonBlockedIndices .add (state .metaData ().index (indexName ).getIndex ());
84+ } else {
85+ state = addBlockedIndex (indexName , randomIntBetween (1 , 5 ), randomIntBetween (0 , 5 ), state );
86+ blockedIndices .put (state .metaData ().index (indexName ).getIndex (), new AcknowledgedResponse (randomBoolean ()));
87+ }
88+ }
89+
90+ final ClusterState updatedState = MetaDataIndexStateService .closeRoutingTable (state , blockedIndices );
91+ assertThat (updatedState .metaData ().indices ().size (), equalTo (nonBlockedIndices .size () + blockedIndices .size ()));
92+
93+ for (Index nonBlockedIndex : nonBlockedIndices ) {
94+ assertIsOpened (nonBlockedIndex .getName (), updatedState );
95+ }
96+ for (Map .Entry <Index , AcknowledgedResponse > blockedIndex : blockedIndices .entrySet ()) {
97+ if (blockedIndex .getValue ().isAcknowledged ()) {
98+ assertIsClosed (blockedIndex .getKey ().getName (), updatedState );
99+ } else {
100+ assertIsOpened (blockedIndex .getKey ().getName (), updatedState );
101+ }
102+ }
103+ }
104+
105+ public void testAddIndexClosedBlocks () {
106+ final ClusterState initialState = ClusterState .builder (new ClusterName ("testAddIndexClosedBlocks" )).build ();
107+ {
108+ final Set <Index > blockedIndices = new HashSet <>();
109+ expectThrows (IndexNotFoundException .class , () ->
110+ MetaDataIndexStateService .addIndexClosedBlocks (new Index []{new Index ("_name" , "_uid" )}, initialState , blockedIndices ));
111+ assertTrue (blockedIndices .isEmpty ());
112+ }
113+ {
114+ final Set <Index > blockedIndices = new HashSet <>();
115+ Index [] indices = Index .EMPTY_ARRAY ;
116+
117+ ClusterState updatedState = MetaDataIndexStateService .addIndexClosedBlocks (indices , initialState , blockedIndices );
118+ assertSame (initialState , updatedState );
119+ assertTrue (blockedIndices .isEmpty ());
120+ }
121+ {
122+ final Set <Index > blockedIndices = new HashSet <>();
123+ ClusterState state = addClosedIndex ("closed" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), initialState );
124+ Index [] indices = new Index []{state .metaData ().index ("closed" ).getIndex ()};
125+
126+ ClusterState updatedState = MetaDataIndexStateService .addIndexClosedBlocks (indices , state , blockedIndices );
127+ assertSame (state , updatedState );
128+ assertTrue (blockedIndices .isEmpty ());
129+ }
130+ {
131+ final Set <Index > blockedIndices = new HashSet <>();
132+ ClusterState state = addClosedIndex ("closed" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), initialState );
133+ state = addOpenedIndex ("opened" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), state );
134+ Index [] indices = new Index []{state .metaData ().index ("opened" ).getIndex (), state .metaData ().index ("closed" ).getIndex ()};
135+
136+ ClusterState updatedState = MetaDataIndexStateService .addIndexClosedBlocks (indices , state , blockedIndices );
137+ assertNotSame (state , updatedState );
138+ assertTrue (blockedIndices .contains (updatedState .metaData ().index ("opened" ).getIndex ()));
139+ assertFalse (blockedIndices .contains (updatedState .metaData ().index ("closed" ).getIndex ()));
140+ assertIsBlocked ("opened" , updatedState , true );
141+ }
142+ {
143+ IllegalArgumentException exception = expectThrows (IllegalArgumentException .class , () -> {
144+ ClusterState state = addRestoredIndex ("restored" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), initialState );
145+ if (randomBoolean ()) {
146+ state = addOpenedIndex ("opened" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), state );
147+ }
148+ if (randomBoolean ()) {
149+ state = addOpenedIndex ("closed" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), state );
150+ }
151+ Index [] indices = new Index []{state .metaData ().index ("restored" ).getIndex ()};
152+ MetaDataIndexStateService .addIndexClosedBlocks (indices , state , new HashSet <>());
153+ });
154+ assertThat (exception .getMessage (), containsString ("Cannot close indices that are being restored: [[restored]]" ));
155+ }
156+ {
157+ IllegalArgumentException exception = expectThrows (IllegalArgumentException .class , () -> {
158+ ClusterState state = addSnapshotIndex ("snapshotted" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), initialState );
159+ if (randomBoolean ()) {
160+ state = addOpenedIndex ("opened" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), state );
161+ }
162+ if (randomBoolean ()) {
163+ state = addOpenedIndex ("closed" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), state );
164+ }
165+ Index [] indices = new Index []{state .metaData ().index ("snapshotted" ).getIndex ()};
166+ MetaDataIndexStateService .addIndexClosedBlocks (indices , state , new HashSet <>());
167+ });
168+ assertThat (exception .getMessage (), containsString ("Cannot close indices that are being snapshotted: [[snapshotted]]" ));
169+ }
170+ {
171+ final Set <Index > blockedIndices = new HashSet <>();
172+ ClusterState state = addOpenedIndex ("index-1" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), initialState );
173+ state = addOpenedIndex ("index-2" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), state );
174+ state = addOpenedIndex ("index-3" , randomIntBetween (1 , 3 ), randomIntBetween (0 , 3 ), state );
175+ final boolean mixedVersions = randomBoolean ();
176+ if (mixedVersions ) {
177+ state = ClusterState .builder (state )
178+ .nodes (DiscoveryNodes .builder (state .nodes ())
179+ .add (new DiscoveryNode ("old_node" , buildNewFakeTransportAddress (), Collections .emptyMap (),
180+ new HashSet <>(Arrays .asList (DiscoveryNode .Role .values ())), Version .V_6_0_0 )))
181+ .build ();
182+ }
183+ Index [] indices = new Index []{state .metaData ().index ("index-1" ).getIndex (),
184+ state .metaData ().index ("index-2" ).getIndex (), state .metaData ().index ("index-3" ).getIndex ()};
185+
186+ ClusterState updatedState = MetaDataIndexStateService .addIndexClosedBlocks (indices , state , blockedIndices );
187+ assertNotSame (state , updatedState );
188+ assertTrue (blockedIndices .contains (updatedState .metaData ().index ("index-1" ).getIndex ()));
189+ assertTrue (blockedIndices .contains (updatedState .metaData ().index ("index-2" ).getIndex ()));
190+ assertTrue (blockedIndices .contains (updatedState .metaData ().index ("index-3" ).getIndex ()));
191+ if (mixedVersions ) {
192+ assertIsClosed ("index-1" , updatedState );
193+ assertIsClosed ("index-2" , updatedState );
194+ assertIsClosed ("index-2" , updatedState );
195+ } else {
196+ assertIsBlocked ("index-1" , updatedState , true );
197+ assertIsBlocked ("index-2" , updatedState , true );
198+ assertIsBlocked ("index-3" , updatedState , true );
199+ }
200+ }
201+ }
202+
44203 public void testValidateShardLimit () {
45204 int nodesInCluster = randomIntBetween (2 ,100 );
46205 ClusterShardLimitIT .ShardCounts counts = forDataNodeCount (nodesInCluster );
@@ -55,7 +214,6 @@ public void testValidateShardLimit() {
55214 .collect (Collectors .toList ())
56215 .toArray (new Index [2 ]);
57216
58- DeprecationLogger deprecationLogger = new DeprecationLogger (logger );
59217 int totalShards = counts .getFailingIndexShards () * (1 + counts .getFailingIndexReplicas ());
60218 int currentShards = counts .getFirstIndexShards () * (1 + counts .getFirstIndexReplicas ());
61219 int maxShards = counts .getShardsPerNode () * nodesInCluster ;
@@ -69,32 +227,115 @@ public static ClusterState createClusterForShardLimitTest(int nodesInCluster, in
69227 int closedIndexShards , int closedIndexReplicas , Settings clusterSettings ) {
70228 ImmutableOpenMap .Builder <String , DiscoveryNode > dataNodes = ImmutableOpenMap .builder ();
71229 for (int i = 0 ; i < nodesInCluster ; i ++) {
72- dataNodes .put (randomAlphaOfLengthBetween (5 ,15 ), mock (DiscoveryNode .class ));
230+ dataNodes .put (randomAlphaOfLengthBetween (5 , 15 ), mock (DiscoveryNode .class ));
73231 }
74232 DiscoveryNodes nodes = mock (DiscoveryNodes .class );
75233 when (nodes .getDataNodes ()).thenReturn (dataNodes .build ());
76234
77- IndexMetaData .Builder openIndexMetaData = IndexMetaData .builder (randomAlphaOfLengthBetween (5 , 15 ))
78- .settings (Settings .builder ().put (IndexMetaData .SETTING_VERSION_CREATED , Version .CURRENT ))
79- .creationDate (randomLong ())
80- .numberOfShards (openIndexShards )
81- .numberOfReplicas (openIndexReplicas );
82- IndexMetaData .Builder closedIndexMetaData = IndexMetaData .builder (randomAlphaOfLengthBetween (5 , 15 ))
83- .settings (Settings .builder ().put (IndexMetaData .SETTING_VERSION_CREATED , Version .CURRENT ))
84- .creationDate (randomLong ())
85- .state (IndexMetaData .State .CLOSE )
86- .numberOfShards (closedIndexShards )
87- .numberOfReplicas (closedIndexReplicas );
88- MetaData .Builder metaData = MetaData .builder ().put (openIndexMetaData ).put (closedIndexMetaData );
235+ ClusterState state = ClusterState .builder (ClusterName .DEFAULT ).build ();
236+ state = addOpenedIndex (randomAlphaOfLengthBetween (5 , 15 ), openIndexShards , openIndexReplicas , state );
237+ state = addClosedIndex (randomAlphaOfLengthBetween (5 , 15 ), closedIndexShards , closedIndexReplicas , state );
238+
239+ final MetaData .Builder metaData = MetaData .builder (state .metaData ());
89240 if (randomBoolean ()) {
90241 metaData .persistentSettings (clusterSettings );
91242 } else {
92243 metaData .transientSettings (clusterSettings );
93244 }
245+ return ClusterState .builder (state ).metaData (metaData ).nodes (nodes ).build ();
246+ }
247+
248+ private static ClusterState addOpenedIndex (final String index , final int numShards , final int numReplicas , final ClusterState state ) {
249+ return addIndex (state , index , numShards , numReplicas , IndexMetaData .State .OPEN , null );
250+ }
251+
252+ private static ClusterState addClosedIndex (final String index , final int numShards , final int numReplicas , final ClusterState state ) {
253+ return addIndex (state , index , numShards , numReplicas , IndexMetaData .State .CLOSE , MetaDataIndexStateService .INDEX_CLOSED_BLOCK );
254+ }
255+
256+ private static ClusterState addBlockedIndex (final String index , final int numShards , final int numReplicas , final ClusterState state ) {
257+ return addIndex (state , index , numShards , numReplicas , IndexMetaData .State .OPEN , MetaDataIndexStateService .INDEX_CLOSED_BLOCK );
258+ }
259+
260+ private static ClusterState addRestoredIndex (final String index , final int numShards , final int numReplicas , final ClusterState state ) {
261+ ClusterState newState = addOpenedIndex (index , numShards , numReplicas , state );
262+
263+ final ImmutableOpenMap .Builder <ShardId , RestoreInProgress .ShardRestoreStatus > shardsBuilder = ImmutableOpenMap .builder ();
264+ for (ShardRouting shardRouting : newState .routingTable ().index (index ).randomAllActiveShardsIt ()) {
265+ shardsBuilder .put (shardRouting .shardId (), new RestoreInProgress .ShardRestoreStatus (shardRouting .currentNodeId ()));
266+ }
267+
268+ final Snapshot snapshot = new Snapshot (randomAlphaOfLength (10 ), new SnapshotId (randomAlphaOfLength (5 ), randomAlphaOfLength (5 )));
269+ final RestoreInProgress .Entry entry =
270+ new RestoreInProgress .Entry (snapshot , RestoreInProgress .State .INIT , Collections .singletonList (index ), shardsBuilder .build ());
271+ return ClusterState .builder (newState ).putCustom (RestoreInProgress .TYPE , new RestoreInProgress (entry )).build ();
272+ }
273+
274+ private static ClusterState addSnapshotIndex (final String index , final int numShards , final int numReplicas , final ClusterState state ) {
275+ ClusterState newState = addOpenedIndex (index , numShards , numReplicas , state );
276+
277+ final ImmutableOpenMap .Builder <ShardId , SnapshotsInProgress .ShardSnapshotStatus > shardsBuilder = ImmutableOpenMap .builder ();
278+ for (ShardRouting shardRouting : newState .routingTable ().index (index ).randomAllActiveShardsIt ()) {
279+ shardsBuilder .put (shardRouting .shardId (), new SnapshotsInProgress .ShardSnapshotStatus (shardRouting .currentNodeId ()));
280+ }
94281
95- return ClusterState .builder (ClusterName .DEFAULT )
96- .metaData (metaData )
97- .nodes (nodes )
282+ final Snapshot snapshot = new Snapshot (randomAlphaOfLength (10 ), new SnapshotId (randomAlphaOfLength (5 ), randomAlphaOfLength (5 )));
283+ final SnapshotsInProgress .Entry entry =
284+ new SnapshotsInProgress .Entry (snapshot , randomBoolean (), false , SnapshotsInProgress .State .INIT ,
285+ Collections .singletonList (new IndexId (index , index )), randomNonNegativeLong (), randomLong (), shardsBuilder .build ());
286+ return ClusterState .builder (newState ).putCustom (SnapshotsInProgress .TYPE , new SnapshotsInProgress (entry )).build ();
287+ }
288+
289+ private static ClusterState addIndex (final ClusterState currentState ,
290+ final String index ,
291+ final int numShards ,
292+ final int numReplicas ,
293+ final IndexMetaData .State state ,
294+ @ Nullable final ClusterBlock block ) {
295+ final IndexMetaData indexMetaData = IndexMetaData .builder (index )
296+ .state (state )
297+ .creationDate (randomNonNegativeLong ())
298+ .settings (Settings .builder ()
299+ .put (SETTING_VERSION_CREATED , Version .CURRENT )
300+ .put (SETTING_NUMBER_OF_SHARDS , numShards )
301+ .put (SETTING_NUMBER_OF_REPLICAS , numReplicas ))
98302 .build ();
303+
304+ final ClusterState .Builder clusterStateBuilder = ClusterState .builder (currentState );
305+ clusterStateBuilder .metaData (MetaData .builder (currentState .metaData ()).put (indexMetaData , true ));
306+
307+ if (state == IndexMetaData .State .OPEN ) {
308+ final IndexRoutingTable .Builder indexRoutingTable = IndexRoutingTable .builder (indexMetaData .getIndex ());
309+ for (int j = 0 ; j < indexMetaData .getNumberOfShards (); j ++) {
310+ ShardId shardId = new ShardId (indexMetaData .getIndex (), j );
311+ IndexShardRoutingTable .Builder indexShardRoutingBuilder = new IndexShardRoutingTable .Builder (shardId );
312+ indexShardRoutingBuilder .addShard (newShardRouting (shardId , randomAlphaOfLength (10 ), true , ShardRoutingState .STARTED ));
313+ for (int k = 0 ; k < indexMetaData .getNumberOfReplicas (); k ++) {
314+ indexShardRoutingBuilder .addShard (newShardRouting (shardId , randomAlphaOfLength (10 ), false , ShardRoutingState .STARTED ));
315+ }
316+ indexRoutingTable .addIndexShard (indexShardRoutingBuilder .build ());
317+ }
318+ clusterStateBuilder .routingTable (RoutingTable .builder (currentState .routingTable ()).add (indexRoutingTable ).build ());
319+ }
320+ if (block != null ) {
321+ clusterStateBuilder .blocks (ClusterBlocks .builder ().blocks (currentState .blocks ()).addIndexBlock (index , block ));
322+ }
323+ return clusterStateBuilder .build ();
324+ }
325+
326+ private static void assertIsOpened (final String indexName , final ClusterState clusterState ) {
327+ assertThat (clusterState .metaData ().index (indexName ).getState (), is (IndexMetaData .State .OPEN ));
328+ assertThat (clusterState .routingTable ().index (indexName ), notNullValue ());
329+ assertIsBlocked (indexName , clusterState , false );
330+ }
331+
332+ private static void assertIsClosed (final String indexName , final ClusterState clusterState ) {
333+ assertThat (clusterState .metaData ().index (indexName ).getState (), is (IndexMetaData .State .CLOSE ));
334+ assertThat (clusterState .routingTable ().index (indexName ), nullValue ());
335+ assertIsBlocked (indexName , clusterState , true );
336+ }
337+
338+ private static void assertIsBlocked (final String indexName , final ClusterState clusterState , final boolean blocked ) {
339+ assertThat (clusterState .blocks ().hasIndexBlock (indexName , MetaDataIndexStateService .INDEX_CLOSED_BLOCK ), is (blocked ));
99340 }
100341}
0 commit comments